webpack 使用详解

150 阅读5分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情

webpack 使用详解

核心概念

Entry

入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。 进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。 每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。

Output

output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。 基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。

Module

模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。

Chunk

代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。

Loader

loader 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript)。 loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。 本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。

Plugin

loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务。 插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。

构建流程

Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程 : 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译。 确定入口:根据配置中的 entry 找出所有的入口文件。 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理。 完成模块编译:在经过第 4 步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系。 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。 在以上过程中,Webpack 会在特定的时间点广播出特定的事件,插件在监听到感兴趣的事件后会执行特定的逻辑,并且插件可以调用 Webpack 提供的 API 改变 Webpack 的运行结果。

使用

1、基本安装

mkdir webpack-demo && cd webpack-demo npm init -y npm install webpack webpack-cli --save-dev

增加 webpack.config.js 文件

const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.resolve(\_\_dirname, 'dist')
}
};
2、加载 css

npm install --save-dev style-loader css-loader

webpack.config.js 增加

   module: {
     rules: [
       {
         test: /\.css$/,
         use: [
           'style-loader',
           'css-loader'
         ]
       }
     ]
   }
3、加载图片

npm install --save-dev file-loader webpack.config.js

      {
         test: /\.(png|svg|jpg|gif)$/,
         use: [
           'file-loader'
         ]
       }
4、加载图片字体等资源
{
  test: /\.(png|svg|jpg|jpeg|gif)$/i,
  type: 'asset/resource',
  },
  {
  test: /\.(woff|woff2|eot|ttf|otf)$/i,
  type: 'asset/resource',
}

5、加载数据资源

npm install --save-dev csv-loader xml-loader

{
    test: /\.(csv|tsv)$/i,
    use: ['csv-loader'],
},
{
    test: /\.xml$/i,
    use: ['xml-loader'],
}
6、输出目录

配置打包生成的目录

entry: {
    index: './src/index.js',
    print: './src/print.js',
},
output: {
    filename: '[name].bundle.js',
    path: path.resolve("./", 'dist')
},
7、HtmlWebpackPlugin

处理 html 模板

const HtmlWebpackPlugin = require('html-webpack-plugin');

plugins: [
    new HtmlWebpackPlugin({
        title: '管理输出',
    }),
]
8、清理 dist 文件夹

先删除原来的 dist 文件夹,再生成新的打包目录

 output: {
     filename: '[name].bundle.js',
     path: path.resolve(__dirname, 'dist'),
    clean: true,
   },
9、manifest
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
new WebpackManifestPlugin({
    fileName: 'manifest.json',
    basePath: '/',
})
10、devtool

1.source-map 大而全,啥都有,就因为啥都有可能会让 webpack 构建时间变长,看情况使用。 2.cheap-module-eval-source-map 这个一般是开发环境(dev)推荐使用,在构建速度报错提醒上做了比较好的均衡。 3.cheap-module-source-map 一般来说,生产环境是不配 source-map 的,如果想捕捉线上的代码报错,我们可以用这个

11、环境变量

env(全局变量) process.env

12、webpack-dev-server
13、构建性能

将 loader 应用于最少数量的必要模块。而非如下:

module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
},
],
},
};
通过使用 include 字段,仅将 loader 应用在实际需要将其转换的模块:
const path = require('path');

module.exports = {
//...
module: {
rules: [
{
test: /\.js$/,
include: path.resolve(__dirname, 'src'),
loader: 'babel-loader',
},
],
},
};

使用 DllPlugin 为更改不频繁的代码生成单独的编译结果。这可以提高应用程序的编译速度,尽管它增加了构建过程的复杂度。

下面几个工具通过在内存中(而不是写入磁盘)编译和 serve 资源来提高性能: webpack-dev-server webpack-hot-middleware webpack-dev-middleware

需要注意的是不同的 devtool 设置,会导致性能差异。 "eval" 具有最好的性能,但并不能帮助你转译代码。 如果你能接受稍差一些的 map 质量,可以使用 cheap-source-map 变体配置来提高性能 使用 eval-source-map 变体配置进行增量编译。

14、热更新
devServer: {
contentBase: './dist',
hot: true,
},

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 17 天,点击查看活动详情