开启掘金成长之旅!这是我参与「掘金日新计划 · 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 天,点击查看活动详情