生产环境
生产环境
在本指南中,我们将深入探讨构建生产级站点或应用程序的最佳实践和工具。
T> 本教程建立在 摇树优化 和 开发环境 的基础上。请确保在继续之前熟悉这些指南中介绍的概念/设置。
配置分离
开发 和 生产 构建的目标差异很大。在 开发 环境中,我们需要强大的源代码映射(source map)和带有实时重新加载或热模块替换的 localhost 服务器。而在 生产 环境中,我们的目标转向压缩 bundle、更轻量的源代码映射以及优化资源以缩短加载时间。基于这种逻辑上的分离,我们通常建议为每种环境编写独立的 webpack 配置。
虽然我们会将 生产 和 开发 特定的部分分离出来,但请注意我们仍会维护一个“公共(common)”配置,以保持代码不重复(DRY)。为了合并这些配置,我们将使用一个名为 webpack-merge 的工具。有了“公共”配置,我们就不必在特定于环境的配置中重复代码。
让我们先安装 webpack-merge,并将之前在指南中已经完成的部分拆分出来:
bash
npm install --save-dev webpack-merge
项目结构
diff
webpack-demo
├── package.json
├── package-lock.json
- ├── webpack.config.js
+ ├── webpack.common.js
+ ├── webpack.dev.js
+ ├── webpack.prod.js
├── /dist
├── /src
│ ├── index.js
│ └── math.js
└── /node_modules
webpack.common.js
diff
+ import path from 'node:path';
+ import { fileURLToPath } from 'node:url';
+ import HtmlWebpackPlugin from 'html-webpack-plugin';
+
+ const __filename = fileURLToPath(import.meta.url);
+ const __dirname = path.dirname(__filename);
+
+ export default {
+ entry: {
+ app: './src/index.js',
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: '生产环境',
+ }),
+ ],
+ output: {
+ filename: '[name].bundle.js',
+ path: path.resolve(__dirname, 'dist'),
+ clean: true,
+ },
+ };
webpack.dev.js
diff
+ import { merge } from 'webpack-merge';
+ import common from './webpack.common.js';
+
+ export default merge(common, {
+ mode: 'development',
+ devtool: 'inline-source-map',
+ devServer: {
+ static: './dist',
+ },
+ });
webpack.prod.js
diff
+ import { merge } from 'webpack-merge';
+ import common from './webpack.common.js';
+
+ export default merge(common, {
+ mode: 'production',
+ });
在 webpack.common.js 中,我们配置了 entry 和 output,并包含了两个环境都需要的插件。在 webpack.dev.js 中,我们将 mode 设置为 development。此外,我们还为开发环境添加了推荐的 devtool(强大的源代码映射)以及 devServer 配置。最后,在 webpack.prod.js 中,mode 设置为 production,它会加载 MinimizerPlugin,该插件最早在摇树优化指南中介绍过。
请注意,在特定于环境的配置中使用了 merge() 调用,以将公共配置合并到 webpack.dev.js 和 webpack.prod.js 中。webpack-merge 工具提供了多种高级合并功能,但就我们的用例而言,目前还不需要用到这些。
NPM 脚本
现在,让我们修改 npm 脚本以使用新的配置文件。对于运行 webpack-dev-server 的 start 脚本,我们将使用 webpack.dev.js;对于运行 webpack 创建生产构建的 build 脚本,我们将使用 webpack.prod.js:
package.json
diff
{
"name": "development",
"version": "1.0.0",
"description": "",
"main": "src/index.js",
"scripts": {
- "start": "webpack serve --open",
+ "start": "webpack serve --open --config webpack.dev.js",
- "build": "webpack"
+ "build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^7.1.3",
"csv-loader": "^3.0.5",
"express": "^5.2.1",
"html-webpack-plugin": "^5.6.6",
"style-loader": "^4.0.0",
"webpack": "^5.105.0",
"webpack-cli": "^7.0.0",
"webpack-dev-middleware": "^8.0.3",
"webpack-dev-server": "^5.2.3",
"webpack-merge": "^6.0.1",
"xml-loader": "^1.2.1"
}
}
可以随时运行这些脚本,看看随着我们继续向 生产 配置添加内容,输出会发生什么变化。
指定模式
许多库会根据 process.env.NODE_ENV 变量来决定库中应包含哪些内容。例如,当 process.env.NODE_ENV 未设置为 'production' 时,某些库可能会添加额外的日志记录和测试以便于调试。但是,当 process.env.NODE_ENV 设置为 'production' 时,它们可能会删除或添加大量代码段,以优化实际用户的使用体验。从 webpack v4 开始,指定 mode 会自动通过 DefinePlugin 为你配置 process.env.NODE_ENV:
webpack.prod.js
diff
import { merge } from 'webpack-merge';
import common from './webpack.common.js';
export default merge(common, {
mode: 'production',
});
T> 从技术上讲,NODE_ENV 是 Node.js 暴露给运行脚本的系统环境变量。按照惯例,服务器工具、构建脚本和客户端库使用它来确定开发与生产行为。与预期相反,process.env.NODE_ENV 在运行 webpack 时,不会在构建脚本 webpack.config.js 内部自动设置。因此,在 webpack 配置中,类似 process.env.NODE_ENV === 'production' ? '[name].[contenthash].bundle.js' : '[name].bundle.js' 的条件判断是不会生效的,除非你通过命令行显式指定 NODE_ENV=production。
如果你使用像 react 这样的库,在添加 DefinePlugin 后,你应该会看到 bundle 大小显著下降。此外,请注意,我们的任何本地 /src 代码也可以利用这一点,因此以下检查是有效的:
src/index.js
diff
import { cube } from './math.js';
+
+ if (process.env.NODE_ENV !== 'production') {
+ console.log('看起来我们正处于开发模式!');
+ }
function component() {
const element = document.createElement('pre');
element.innerHTML = [
'Hello webpack!',
'5 cubed is equal to ' + cube(5)
].join('\n\n');
return element;
}
document.body.appendChild(component());
代码压缩
Webpack v4+ 在 生产模式 下默认会压缩你的代码。
请注意,虽然 MinimizerPlugin 是压缩的不错起点且被默认使用,但还有其他选择:
如果你决定尝试其他压缩插件,请确保你的新选择也能像摇树优化指南中描述的那样移除死代码,并将其作为 optimization.minimizer 提供。
源代码映射
我们鼓励你在生产环境中启用源代码映射,因为它们对于调试以及运行基准测试很有用。也就是说,你应该选择一个构建速度较快且推荐用于生产环境的选项(参见 devtool)。在本指南中,我们将在 生产 配置中使用 source-map 选项,而不是 开发 中使用的 inline-source-map:
webpack.prod.js
diff
import { merge } from 'webpack-merge';
import common from './webpack.common.js';
export default merge(common, {
mode: 'production',
+ devtool: 'source-map',
});
T> 避免在生产环境中使用 inline-*** 和 eval-*** 选项,因为它们会增加 bundle 大小并降低整体性能。
压缩 CSS
在生产环境中压缩 CSS 至关重要。请参阅 为生产环境压缩 部分。
CLI 替代方案
上面描述的许多选项都可以通过命令行参数进行设置。例如,可以通过 --optimization-minimize 设置 optimization.minimize,通过 --mode 设置 mode。运行 npx webpack --help=verbose 查看完整的 CLI 参数列表。
虽然这些简写方法很有用,但我们建议在 webpack 配置文件中设置这些选项,以获得更好的可配置性。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
