webpack 常用核心配置解析
entry(入口)
entry 指定了构建的起点。webpack 会从这个文件开始递归解析依赖,最终生成对应的 bundle。
它的值可以是字符串、数组或对象。对象形式通常用于多入口场景,键名会成为输出 chunk 的名称:
module.exports = {
entry: {
app: './src/index.js',
admin: './src/admin.js'
}
};
output(输出)
output 用于定义打包产物如何输出。其中两个最常用的字段是 filename 和 path:
- filename:生成的资源文件名,支持
[name]、[hash]、[chunkhash]等占位符。 - path:产物在本地磁盘上的绝对路径。
const path = require('path');
module.exports = {
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'build')
}
};
chunkFilename(异步 chunk 命名)
对于没有在 entry 中声明、而是通过动态导入(按需加载)生成的代码块,需要使用 chunkFilename 来命名。
module.exports = {
output: {
filename: '[name].js',
chunkFilename: '[name].async.js'
}
};
配合 import() 或 require.ensure 使用时,被分割出来的模块就会以该规则生成独立的 chunk。
// 点击按钮后才会加载这个异步模块
document.querySelector('#btn').addEventListener('click', () => {
import('./modules/tool').then(({ default: tool }) => {
tool.init();
});
});
publicPath(公共资源路径)
output.path 描述的是打包产物存放在本地磁盘的目录;而 publicPath 描述的是运行时浏览器访问这些静态资源的 URL 前缀。
例如,把 dist 目录部署到 CDN 或二级路径时,可以这样配置:
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/assets/'
}
};
这样,HTML 中引用的脚本路径会变为 /assets/main.js,而不是相对路径。
mode(模式)
mode 用于告诉 webpack 当前所处的构建环境,常见的有 development 和 production。不同模式会触发不同的内置优化策略,例如 production 模式会默认启用代码压缩。
module.exports = {
mode: 'production'
};
module.rules(Loader 配置)
webpack 默认只能理解 JavaScript。要处理 CSS、图片、TypeScript 等模块,必须通过 Loader 进行转换。Loader 本质上是一个函数,它接收源文件并返回转换后的结果。
每条规则通常包含:
- test:正则匹配需要处理的文件类型。
- include / exclude:限定或排除某些目录,缩小查找范围。
- use:指定应用的 Loader,多个 Loader 时默认从右向左执行。
- enforce:强制某个 Loader 在最前或最后执行。
module.exports = {
module: {
rules: [
{
test: /\.jsx?$/,
include: path.resolve(__dirname, 'src'),
exclude: /node_modules/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env', '@babel/preset-react'],
cacheDirectory: true
}
}
]
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
如果需要某个 Loader 先执行或后执行,可以添加 enforce:
{
test: /\.js$/,
enforce: 'pre',
loader: 'eslint-loader'
}
enforce: 'pre" 表示最先执行,enforce: "post" 表示最后执行。
module.noParse(跳过解析)
对于一些不依赖模块规范的第三方库,可以让 webpack 跳过对它的递归解析,从而加快构建速度。这些库中不应包含 require、import、define 等模块化语句。
module.exports = {
module: {
noParse: /jquery|lodash/
}
};
resolve.alias(路径别名)
alias 可以把较长的导入路径映射成更简短的别名,使项目结构更清晰。
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@components': path.resolve(__dirname, 'src/components')
}
}
};
配置后,代码中可以这样引入组件:
import Header from '@components/Header';
resolve.extensions(自动补全后缀)
当使用 import 导入文件没有写后缀时,webpack 会按照 extensions 配置的顺序依次查找文件。默认值只包含 .js 和 .json。
module.exports = {
resolve: {
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json']
}
};
externals(排除打包)
如果某些库已经通过 CDN 或全局变量在运行时提供,可以使用 externals 告诉 webpack 不要把它们打包进产物。
module.exports = {
externals: {
react: 'React',
'react-dom': 'ReactDOM'
}
};
代码中仍然可以正常引入,但 webpack 不会把 react 和 react-dom 的代码打进 bundle:
import React from 'react';
import ReactDOM from 'react-dom';