对 webpack 的打包有了一个基础的体验之后,可以开始尝试自定义一些配置了。
在开始配置之前,先了解一下 webpack 的四个核心概念。
webpack的四个核心概念
即 entry (入口)、output (出口)、loader (模块转换器)、plugin (插件)
- entry (入口)
告诉 wbpack 要使用哪个文件作为构建项目的起点。默认为 ./src/index.js
webpack 从入口开始,根据模块间的依赖关系,递归解析和处理所有资源文件。
- output (出口)
告诉 webpack 打包后的文件名和路径。
主要输出文件默认为 ./dist/main.js,其他文件放在 ./dist 文件夹中。
module.exports = {
mode: 'development',
entry: path.resolve(__dirname, '../src/index.js'),
output: {
filename: '[name].[hash:8].js',
path: path.resolve(__dirname, '../dist'),
},
}
- loader (模块转换器)
实现对不同格式文件的处理,比如,将 sass 转换为 css,将 typescript 转换为 js 等。
转换这些文件,从而使其能够被添加到依赖图中。
为什么要转换?
原因是,webpack 本身只理解 javascript 和 JSON 文件,别的认不得,所以需要 loader 来“翻译”一下。
loader 本质是一个函数,对接收到的内容进行转换,返回转换后的结果。
- plugin (插件)
即扩展插件。插件可以扩展 webpack 的功能。作用更大,范围更广,可以打包优化、资源管理和注入环境变量等。
在 webpack 运行的生命周期中,会广播出许多事件,plugin 可以监听这些事件,在合适的实际,通过 webpack 提供的 api,改变输出结果。
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
module.exports = {
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
plugins: [new HtmlWebpackPlugin({ template: './src/index.html' })],
};
plugins 和 loaders 比较:
- loaders 负责的是处理源文件,如 css、jsx,一次只处理一个文件;
- plugins 并不是直接操作单个文件,而是对整个构建过程起作用。
自定义配置 entry 和 output
下面开始自定义 webpack 配置啦,新建一个 build/webpack.config.js 文件。
然后把 打包命令改为:
"scripts": {
"build": "webpack --config build/webpack.config.js"
},
1. entry (入口)
entry 可以是一个或多个。格式可以是字符串、数组和对象。
- entry 为字符串:单个入口。输出一个打包后的文件,默认为 main.js。
在 build/webpack.config.js 输入:
module.exports = {
mode: 'development', // 模式
entry: './src/index.js',
}
npm run build,会发现生成了 dist 文件夹,里面有个 main.js,即打包后的结果。
- entry 为数组:多个入口。输出一个打包后的文件。
entry: ['./src/index.js', './src/test.js'],
打包后,生成的 main.js 里面包含这两个js的内容。
- entry 为对象:多个入口,有几个输入就有几个输出。输出文件的文件名称就是对象的key。
entry: {
output_index: './src/index.js',
output_test: './src/test.js'
},
打包后,dist里面有两个文件:
2. output (出口)
指明 webpack 打包后的资源输出到哪里,以及如何命名。
将 webpack.config.js 改为:
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
filename: '[name].js', // 打包后资源的入口文件名
path: path.resolve(__dirname, '../dist'), // 打包后资源存放的路径
}
}
output 的其他参数:
output.clean(用于清理 dist 文件夹)
webpack 5.20版本以后可以用 output.clean 代替 clean-webpack-plugin,用于清除dist文件。
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../dist'),
clean: true,
}
注释区
1. 关于 __dirname
__dirname: 当前文件所在文件夹的完整绝对路径。
在上面这个例子里,build/webpack.config.js 里面的 __dirname 是:
/Users/lilei/river/webpack-0222/01-init/build
2. 关于 path.resolve()
参数为个数不定的字符串,返回一个字符串。
原理:从后往前依次拼接,最终得到一个绝对路径字符串。
注意:以 / 开头为绝对路径,如果处理完所有参数后,还未得到绝对路径,则会加上当前工作目录的绝对路径。
再注意:当前文件的 __dirname 是:
/Users/lilei/river/webpack-0222/01-init/build
而当前工作目录是:/Users/lilei/river/webpack-0222/01-init
规则:
- 以
/开头的,不会拼接前面的路径,因为它本身就是绝对路径了; - 以
../开头的,会拼接前面的路径,把最后一节替换掉; - 以
./开头的,或者不带/的,会拼接前面的路径,跟着后面。
path.resolve('./cc'); // /Users/lilei/river/webpack-0222/01-init/cc
path.resolve('/aa/bb', 'cc'); // /aa/bb/cc
path.resolve('/aa/bb', './cc'); // /aa/bb/cc
path.resolve('/aa/bb', '../cc'); // /aa/cc
path.resolve('/aa/bb', '/cc'); // /cc
path.resolve('/root', './aa/bb', '../cc'); // /root/aa/cc
path.resolve('root', './aa/bb', '../cc'); // /Users/lilei/river/webpack-0222/01-init/root/aa/cc