webpack 的基本概念
- Published on
- — 1690 Words
- Authors
- Name
- Richard Shih
- @realshiddong
webpack 是一个现代 JavaScript 应用程序的静态模块打包工具。 当 webpack 处理应用程序时,它会将一切资源都看作是模块,不管是代码资源如 JS、CSS 等,还是非代码资源如图片、字体等,这些模块之间是会存在依赖关系的。 从入口开始,它会递归地构建一个依赖关系图,其中包含应用程序所需的每个模块,然后将这些模块打包成一个或多个bundle。

在 webpack 中,entry、output、loader、plugins 和 mode 等配置项决定了如何构建依赖关系图。我们首先了解一下它们的基本概念。
基本配置项
entry
webpack 是根据入口文件找到它的所有依赖,而依赖又会有新的依赖,从而不断的加入到依赖关系图中。
在我们常见的项目中,如果是单页应用,那么入口一般只有一个;如果是多个页面的项目,那么经常是一个页面会对应一个构建入口,即具有多个入口。 在 webpack 的配置文件中使用 entry 用来指定打包入口,支持两种配置方式:单入口、多入口。
单入口
只有一个入口时,entry 是一个字符串。
module.exports = {
entry: './src/index.js',
}
多入口
有多个入口时,entry 是一个对象。
module.exports = {
entry: {
app: './src/app.js',
admin: './src/admin.js',
},
}
output
output 用来指定将构建结果输出到具体的磁盘目录与文件名。即使可以存在多个 entry 起点,但只能指定一个 output 配置。
可以看上面给出的 webpack 官网图片右侧,构建结果包含 JS、CSS、图片等静态资源文件。
单入口
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
},
}
多入口
entry 是可以有多个入口的,但 output 只会有一个,此时是通过占位符来确保文件名的唯一。
module.exports = {
entry: {
app: './src/app.js',
search: './src/search.js',
},
output: {
filename: '[name].js', // 通过占位符确保⽂件名称的唯⼀
path: path.join(__dirname, 'dist'),
},
}
loaders
其实,webpack 原生只支持 JS 和 JSON 两种文件类型,而对于其他类型的文件,诸如 jsx/tsx 等语法糖、css(包括 less, sass, stylus 等)、图片、字体等文件,webpack 并不知道它们是什么。 此时,需要通过 loaders 去支持 webpack 处理其它文件类型,把它们转换成有效的模块,webpack 在解析时才可以将它们添加到依赖关系图中。
Loader 本身是一个函数,接受源文件作为参数,返回转换的结果。
使用方式
在 webpack 配置文件中,loaders 的位置是放在 module.rules 数组中,其中 test
指定文件的匹配规则,use
指定使用的 loader 名称。
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js',
},
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
}
常用的 loaders
官方推荐的常用 loader 列表见:
类型 | 名称 | 描述 |
---|---|---|
语法转换 | babel-loader | 将 ES6、ES7 等 JS 新特性的语法转换为 ES5 |
ts-loader | 将 TS 文件转换成 JS 文件 | |
样式 | css-loader | 支持 .css 文件的加载和解析 |
less-loader | 将 less 文件转换成 css | |
sass-loader | 将 sass/scss 文件转换成 css | |
style-loader | 将 css 添加到 DOM 的内联样式标签 style 里 | |
stylus-loader | 将 stylus 文件转换成 css | |
postcss-loader | 用 postcss 来处理 CSS | |
其他文件 | file-loader | 解析图片、字体等 |
url-loader | 和 file-loader 类似,但是当文件小于设定的limit时可以返回一个 Data Url | |
raw-loader | 将文件以字符串形式导入 | |
其他 | thread-loader | 多进程打包 JS 和 CSS |
plugins
plugins 是用来增强 webpack 的功能,通常是⽤于 bundle ⽂件的优化、资源管理和环境变量注⼊等。它们是作⽤于整个构建过程的。
使用方式
module.exports = {
entry: './src/index.js',
output: {
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html’
})
]
};
常见的 plugins
官方推荐的常用 loader 列表见:
名称 | 描述 |
---|---|
CopyWebpackPlugin | 将文件或文件夹拷贝到构建的输出目录 |
HtmlWebpackPlugin | 创建 html 文件去承载输出的 bundle,一个页面对应一个 HtmlWebpackPlugin,多个页面时需要在 plugins 数组中添加多个配置 |
TerserPlugin | JS 文件压缩 |
已废弃的著名 plugins
- CommonsChunkPlugin
其作用是将 chunks 相同的模块代码提取成公共的 JS,在 webpack 4 中已经删除CommosChunksPlugin,改为 optimization.splitChunks 了,见 SplitChunksPlugin
module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,
minRemainingSize: 0,
minChunks: 1,
maxAsyncRequests: 30,
maxInitialRequests: 30,
enforceSizeThreshold: 50000,
cacheGroups: {
defaultVendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
}
- CleanWebpackPlugin
现已改为使用 output.clean 进行配置:
module.exports = {
output: {
filename: '[name].bundle.js',
path: path.join(__dirname, 'dist'),
clean: true,
},
}
mode
在 webpack v4 中引入了 mode 的配置,设置 mode 后可以自动开启 webpack 内置的函数,达到在相应环境下的优化,实现零配置。 Mode ⽤来指定当前的构建环境是:production、development、none,默认值为 production。
选项 | 描述 |
---|---|
development | 将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 development。 开启 NamedChunksPlugin 和 NamedModulesPlugin。 |
production | 会将 DefinePlugin 中 process.env.NODE_ENV 的值设置为 production。 开启 FlagDependencyUsagePlugin,FlagIncludedChunksPlugin,ModuleConcatenationPlugin,NoEmitOnErrorsPlugin 和 TerserPlugin 。 |
none | 不使用任何默认优化选项 |
配置示例
webpack 默认的配置文件是 webpack.config.js,且可以在命令行通过 webpack --config 指定配置文件。
从 v4.0.0 开始,由于引入了 mode 可以开启默认的配置,webpack 可以不用再引入一个配置文件来打包项目。 然而,webpack 会假定项目的入口起点为 src/index.js,然后会在 dist/main.js 输出结果,并且在生产环境开启压缩和优化,如果跟你的项目不符合,大概率还是要自定义配置的。
module.exports = {
entry: './src/index.js', // 1.打包的入口文件,默认入口文件为 ./src/index.js
// output: './dist/main.js',
output: { // 2.打包的输出,默认输出文件为 ./dist/main.js
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
mode: 'production', // 3.环境模式
module: {
rules: [ // 4.loaders 的配置
{ test: /\.txt$/, use: 'raw-loader' }
]
},
plugins: [ // 5.plugins 的配置
new HtmlWebpackPlugin({
template: './src/index.html’
})
]
};
使用 npm script 运行 webpack 即可。
{
"name": "app",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"build": "webpack"
}
}