本文基于:峰华前端工程师--30分钟掌握Webpack

为什么使用 Webpack

在我们进行传统网页开发中,会在 index.html 中引入大量的 js 和 css 文件,不仅可能会导致命名冲突,还会使页面体积变大,因为如果引用了第三方库,需要加载所有的代码。而在 node.js 出现后,javascript 项目支持通过 require 支持模块化开发了,并且支出 npm 方便地管理依赖。

借着 node.js 和浏览器js 的一致性,前端项目开始在 node.js 下开发,完成之后把代码构建成浏览器支持的形式。对于 react 或 vue 这种组件化的开发方式,因为有很多分散的文件,那么久特别需要这样的构建操作。

Webpack 就是进行这一步构建操作的,把 node.js 模块化的代码转化为浏览器可执行的代码。它提供了 import 和 export ES6模块化语法的支持,然后通过分析代码中 import 导入的依赖,把需要的代码加载进来。在 Webpack 中,任何文件都可以通过 import 导入,只要有对应的 loader 就可以了。在打包过程中,还可以通过插件来干预打包过程,例如剔除不必要的代码,形成体积更小的项目。

创建项目

  • 打开命令行工具,我们在这里创建一个名为 blog 的博客项目:

    mkdir blog
    cd blog
    yarn init -y
    (或者npm init)
  • 添加 webpack 依赖:

    yarn add webpack webpack-cli --dev
  • 使用 VSCode 打开项目:

    code .

初出茅庐

  • 在 blog 项目下新建 src 文件下,创建 index.js:

    console.log("Hello World");

    我们先只做一个简单的输出.

  • 在 blog 项目下新建 index.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    </head>
    <body>
    <h1>Hello World</h1>
    <script src="./dist/index.js"></script>
    </body>
    </html>
  • 使用 LiveServer 查看刚刚所编写的 html页面:

    可以看到浏览器成功显示了 "Hello World",并且控制台也能够成功输出.

  • 尝试使用 webpack 打包

    打开控制台,输入 npx webpack

npx 能够直接运行 node_modules 下面安装的库的自带的命令行,而不用写 node_modules 下一串的绝对路径。

打包完成后可以看到项目里面生成了一个 dist 目录,里面有一个 main.js 文件,其内部的内容和我们刚刚所编写的 index.js 的文件一模一样,这是因为我们并没有使用任何 import 来导入其他的依赖。

使用 import 导入依赖

  • 在 src 下新建一个 data.js 文件:

    export function getBlogPosts() {
    return ["博客1", "博客2", "博客3"];
    }
  • 在 index.js 中导入 data.js 中的函数并调用:

    import { getBlogPosts } from "./data";
    
    console.log(getBlogPosts());
  • 重新使用 webpack 打包以下,查看结果:

    npx webpack

    现在进入 /dist/main.js 中看一下,代码被简化成了直接输出刚才我们所编写的数组的语句,说明 webpack 自动判断了我们所编写代码的逻辑,并通过 import 语句得到了我们所引入的代码,分析后生成新的 js 文件.

  • 在网页中查看下结果:

    成功地输出了数组.

Webpack 配置文件

webpack 的配置文件可以说是 webpack 最核心的部分了,我们可以在配置文件中修改入口和出口文件、通过 loader 加载不同类型的文件和使用 plugins 对代码做其他的操作。

尝试修改打包后生成文件的名称

  • 在项目中新建 webpack.config.js 文件:

    const path = require("path");
    
    module.export = {
    mode: "development",
    // 设置为开发模式,方便调试
    entry: "./src/index.js",
    output: {
    filename: "dist.js",
    path: path.resolve(__dirname, "dist"),
    // 设置文件名和目录
    }
    }
  • 执行 npx webpack 命令打包

    可以看到 dist 文件夹下多了个 dist.js 文件.

使用模块化语法

  • 修改 /index.html 的 script 标签:

    <script src="./dist/dist.js"></script>

    将 main.js 修改成为我们刚刚使用 webpack 打包生成的 dist.js

  • 修改 /src/index.js 文件,将之前编写的数组变成 ul 元素插入页面中:

    const blogs = getBlogPosts();
    
    const ul = document.createElement("ul");
    blogs.forEach(blog => {
    const li = document.createElement("li");
    li.innerText = blog;
    ul.appendChild(li);
    }) document.body.appendChild(ul);
  • npx webpack:

    列表成功插入到了页面.

引入 css

  • 在 src 下新建 style.css 文件:

    h1 {
    color: blueviolet;
    }

    这里只是简单地改变 h1 标签的颜色.

  • 在 /src/index.js 中引入 css 文件:

    import "./style.css";
  • 安装 loader:

    打开控制台,输入:

    yarn add --dev style-loader css-loader
  • 在 webpack.config.js 中配置 loader

    module.exports = {
    mode: "development",
    output: {...},
    ... module: {
    rules: [{
    test: /\.css$/i,
    use: ["style-loader", "css-loader"],
    }]
    }
    }

    module -> rules -> test 内是一个正则表达式,表示以 .css 结尾的文件.

    use 属性下是所使用的 loader

  • 再次使用 npx webpack 打包:

    可以看到,刚才写的样式生效了.

加载图片

  • webpack 原生支持图片等静态文件,但是需要在 webpack.config.js 中编写配置:

    module.exports = {
    ...
    module: {
    rules: [
    ...
    {
    test: /\.(png|svg|jpg|jpeg|gif)$/i,
    type: "assets/resource",
    }]
    }
    }
  • 在 src 下载新建 assets/ 文件夹,放入一张图片:

  • 在 index.js 中引入图片:

    import AbcImage from "./assets/abc.png"
    
    ...
    
    const image = document.createElement("img");
    image.src = AbcImage; document.body.prepend(image);
  • npx webpack:

自动生成 HTML

上述的例子中,我们只是使用 webpack 来打包 js 和 css 文件,并手动的导入编写好的 html 中,使用下面的插件,就可以自动为我们生成 HTML 文件。

  • 安装插件:

    yarn add html-webpack-plugin --dev
  • 使用插件:

    const HtmlWebpackPlugin = require("html-webpack-plugin");
    ... plugins: [new HtmlWebpackPlugin({
    title: "博客列表",
    // 这里可以自定义网页的标题
    })],
  • npx webpack:

    可以看到生成了和刚才相同的页面

使用 webpack 打包出来的网页没有显示 <h1>Hello World</h1> 的原因是 这个标签是我们自己写的

  • 定义打包好 html 文件的网页标题

    我们使用 html-webpack-plugins 打包生成的文件名默认是 Webpack App,其实网页标题是可以在插件内传递参数来更改的:

    plugins: [new HtmlWebpackPlugin({
    title: "博客列表",
    })],

Babel

有时我们的代码可能需要运行在更低版本的浏览器上,这些浏览器可能并不支持我们所写的更高级的代码,这时就需要用到 babel 转译工具来使我们的代码变成浏览器能够识别的代码。

  • 安装 babel-loader 相关依赖:

    yarn add --dev babel-loader @babel/core @babel/preset-env
  • 在 webpack.config.js 中添加配置:

    rules: [
    ...
    {
    test: /\.js$/, // 识别js为结尾的文件
    exclude: /node_modules/, //不解释node_modules/下的文件
    use: {
    loader: "babel-loader",
    options: {
    presets: ["@babel/preset-env"]
    }
    }
    }]

    这里可以在 module.exports 下配置 devtool="inline-source-map" 方便查看打包后的源码

  • 使用 npx webpack 重新打包下,进入 dist/dist.js 查看相关代码:

    /* 打包前的 */
    blogs.forEach(blog => {
    const li = document.createElement("li");
    li.innerText = blog;
    ul.appendChild(li);
    })
    blogs.forEach(function (blog) {
    var li = document.createElement("li");
    li.innerText = blog;
    ul.appendChild(li);
    });

    可以看到 箭头函数已经被转换成了 .forEach 的形式,增强了对浏览器的兼容性。

使用 Terser 插件压缩打包后的代码

  • 安装插件:

    yarn add --dev terser-webpack-plugin
  • 配置:

    // webpack.config.js
    const TerserPlugin = require("terser-webpack-plugin"); module.exports = {
    ...
    optimization: {
    minimize: true,
    minimizer: [new TerserPlugin()],
    },
    }
  • 打包: npx webpack

    可以看到我们打包生成的 js 文件都被紧密地写在了一起,右键属性查看文件大小也要比之前的小一些。

使用 DevServer 插件自动打包

  • 安装:

    yarn add -dev webpack-dev-server
  • 配置:

    module.exports = {
    ...
    devServer: {
    static: "./dist",
    },
    }

    为了我们以后方便运行开发服务器,还需要在 package.json 里添加一个 script:

    {
    ...
    "scripts": {
    "start": "webpack serve --open"
    },
    }
  • 启动服务器:

    yarn start
    // 或
    npm run start
  • 尝试一下 "热更新?"

    在 index.js 下添加如下代码:

    const header1 = document.createElement("h1");
    header1.innerText = "Hello";
    document.body.appendChild(header1);
  • 保存,查看网页

    这里不在使用 VsCode 的 Live Server 插件了,而是在浏览器地址栏输入命令行中输出的地址:

    成功!

    那么 webpack 是如何实现热更新的呢?其实是在我们每次保存时,插件自动生成新的 dist.js 并把之前的 dist.js 写入缓存,这或多或少会增加我们电脑的开销。但 webpack 贴心的为我们想到了这一点。

  • 每次打包生成新的 /dist.js

    配置 webpack.config.js

    output: {
    filename: "[name].[contenthash].js",
    // name 默认为 main
    path: path.resolve(__dirname, "dist"),
    },

    更改下 index.js 代码,运行 npx webpack

    可以看到生成了文件后缀名不同的文件,这样可以避免由于浏览器缓存机制而导致更新不及时的问题。

配置目录别名:

和之前写的 https://www.cnblogs.com/hhsk/p/16460701.html 大同小异

  • 配置:
    // webpack.config.js
    module.exports = {
    ...
    resolve: {
    alias: {
    assets: path.resolve(__dirname, "src/assets")
    }
    }
    }

30分钟掌握 Webpack的更多相关文章

  1. 30分钟学webpack实战

    阅读目录 一:什么是webpack? 他有什么优点? 二:如何安装和配置 三:理解webpack加载器 四:理解less-loader加载器的使用 五:理解babel-loader加载器的含义 六:了 ...

  2. 30分钟手把手教你学webpack实战

    30分钟手把手教你学webpack实战 阅读目录 一:什么是webpack? 他有什么优点? 二:如何安装和配置 三:理解webpack加载器 四:理解less-loader加载器的使用 五:理解ba ...

  3. 每天记录一点:NetCore获得配置文件 appsettings.json vue-router页面传值及接收值 详解webpack + vue + node 打造单页面(入门篇) 30分钟手把手教你学webpack实战 vue.js+webpack模块管理及组件开发

    每天记录一点:NetCore获得配置文件 appsettings.json   用NetCore做项目如果用EF  ORM在网上有很多的配置连接字符串,读取以及使用方法 由于很多朋友用的其他ORM如S ...

  4. 30分钟掌握ES6/ES2015核心内容(下)

    在 30分钟掌握ES6/ES2015核心内容(上)我们讲解了es6最常用的一些语法:let, const, class, extends, super, arrow functions, templa ...

  5. 【微信小程序项目实践总结】30分钟从陌生到熟悉 web app 、native app、hybrid app比较 30分钟ES6从陌生到熟悉 【原创】浅谈内存泄露 HTML5 五子棋 - JS/Canvas 游戏 meta 详解,html5 meta 标签日常设置 C#中回滚TransactionScope的使用方法和原理

    [微信小程序项目实践总结]30分钟从陌生到熟悉 前言 我们之前对小程序做了基本学习: 1. 微信小程序开发07-列表页面怎么做 2. 微信小程序开发06-一个业务页面的完成 3. 微信小程序开发05- ...

  6. 30分钟学会XAML

    1.狂妄的WPF 相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API.例如:WinForm(带控件表单).GDI+(2D图形).DirectX API(3D图形)以及流媒体和 ...

  7. Shell脚本编程30分钟入门

    Shell脚本编程30分钟入门 转载地址: Shell脚本编程30分钟入门 什么是Shell脚本 示例 看个例子吧: #!/bin/sh cd ~ mkdir shell_tut cd shell_t ...

  8. JS组件系列——又一款MVVM组件:Vue(一:30分钟搞定前端增删改查)

    前言:关于Vue框架,好几个月之前就听说过,了解一项新技术之后,总是处于观望状态,一直在犹豫要不要系统学习下.正好最近有点空,就去官网了解了下,看上去还不错的一个组件,就抽空研究了下.最近园子里vue ...

  9. 2016windows(10) wamp 最简单30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world

    2016最简单windows(10) wamp 30分钟thrift入门使用讲解,实现php作为服务器和客户端的hello world thrift是什么 最简单解释 thrift是用来帮助各个编程语 ...

随机推荐

  1. Harbor企业级私服Docker镜像仓库搭建及应用

    一.简介 Docker Hub作为Docker默认官方公共镜像,如果想要自己搭建私有镜像,Harbor是企业级镜像库非常好的选择. 所谓私有仓库,也就是在本地(局域网)搭建的一个类似公共仓库的东西,搭 ...

  2. 2022-7-21 第七组 pan小堂 继承与super与this

    1.继承 1.1继承的概述 在现实生活中,继承一般指的是子女继承父辈的财产.在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系. 1.2继承的格式 class 子类 ...

  3. 从RabbitMQ平滑迁移到RocketMQ技术实战

    作者:vivo 互联网中间件团队- Liu Runyun 大量业务使用消息中间件进行系统间的解耦.异步化.削峰填谷设计实现.公司内部前期基于RabbitMQ实现了一套高可用的消息中间件平台.随着业务的 ...

  4. 非常全的一份Python爬虫的Xpath博文

    非常全的一份Python爬虫的Xpath博文 Xpath 是 python 爬虫过程中非常重要的一个用来定位的一种语法. 一.开始使用 首先我们需要得到一个 HTML 源代码,用来模拟爬取网页中的源代 ...

  5. HCIA-Datacom 3.1 实验一:以太网基础与VLAN配置实验

    实验介绍: 以太网是一种基于CSMA/CD(Carrier Sense Multiple Access/Collision Detection)的共享通讯介质的数据网络通讯技术.当主机数目较多时会导致 ...

  6. 微软Azure配置中心 App Configuration (一):轻松集成到Asp.Net Core

    写在前面 在日常开发中,我这边比较熟悉的配置中心有,携程Apollo,阿里Nacos(配置中心,服务治理一体) 之前文章: Asp.Net Core与携程阿波罗(Apollo)的第一次亲密接触 总体来 ...

  7. what the difference betweent pin page and lock page ?

    以前在项目中,大家为了避免自己使用的page被换出,使用的方式是mlock,从mlock的实现的看,它限制了page被swap, 然后在一个swap off的系统中,这样其实和mlock调用与否没有关 ...

  8. 检查一个数值是否为有限的Number.isFinite()

    如果参数类型不是数值,Number.isFinite()一律返回false. Number.isFinite(15); // true Number.isFinite(0.8); // true Nu ...

  9. 渗透攻防Web篇-深入浅出SQL注入

    1 背景 京东SRC(Security Response Center)收录大量外部白帽子提交的sql注入漏洞,漏洞发生的原因多为sql语句拼接和Mybatis使用不当导致. 2 手工检测 2.1 前 ...

  10. CF593D Happy Tree Party(不用树剖)

    题面 题解 我们发现,对于除法有效的xi最小为2,yi最多除log次就会变成0,所以我们可以每次找路径上下一个>=2的xi,暴力除,当发现y=0时就停止 于是我们维护每个点向上走一直走到根最近的 ...