webpack学习之路(七)
生产环境构建
本节我们将深入了解一些应用于构建网站和应用的最佳实践和工具。
配置
开发环境和生产环境的构建目标差异很大。在开发环境中我们需要具有强大的实时重新加载和模块热替换功能的source map和localhost server 。而在生产环境中,我们的目标变成了更小的输出包、更轻量的source map和更好的资源优化来减少加载时间。遵循逻辑分离我们推荐为每个环境编写独立的webpack配置。
虽然我们对生产环境和开发环境做了略微区分,但是遵循不重复原则DRY(don't repeat yourself)还是保留一个通用配置。为了整合这些配置我们需要一个webpack-merge插件。有了通用配置我们就不用在特定环境的配置中重复代码了。
安装webpack-merge插件并把之前成型了的代码分离:
npm install --save-dev webpack-merge
project
webpack-demo |- package.json - |- webpack.config.js + |- webpack.common.js + |- webpack.dev.js + |- webpack.prod.js |- /dist |- /src |- index.js |- math.js |- /node_modules
webpack.common.js
+ const path = require('path');
+ const CleanWebpackPlugin = require('clean-webpack-plugin');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
+
+ module.exports = {
+ entry: {
+ app: './src/index.js'
+ },
+ plugins: [
+ new CleanWebpackPlugin(['dist']),
+ new HtmlWebpackPlugin({
+ title: 'Production'
+ })
+ ],
+ output: {
+ filename: '[name].bundle.js',
+ path: path.resolve(__dirname, 'dist')
+ }
+ };
webpack.dev.js
+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+ mode: 'development',
+ devtool: 'inline-source-map',
+ devServer: {
+ contentBase: './dist'
+ }
+ });
webpack.prod.js
+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+ mode: 'production',
+ });
在webpack.common.js中我们配置了input和output并引入了两种环境都需要的插件。在webpack.dev.s中我们把mode设置为了开发模式,同时添加了推荐的开发模式调试工具(强大的 source mapping)以及简单的devServer配置。最后在webpack.prod.js中我们把模式设置为了会使用UglifyJSPlugin的生产模式。
NPM脚本:
现在根据新的配置修改一下启动脚本。我们将使用npm start作为开发环境脚本,npm run build作为生产环境脚本。
package.json
{ "name": "development", "version": "1.0.0", "description": "", "main": "src/index.js", "scripts": { - "start": "webpack-dev-server --open", + "start": "webpack-dev-server --open --config webpack.dev.js", - "build": "webpack" + "build": "webpack --config webpack.prod.js" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "clean-webpack-plugin": "^0.1.17", "css-loader": "^0.28.4", "csv-loader": "^2.1.1", "express": "^4.15.3", "file-loader": "^0.11.2", "html-webpack-plugin": "^2.29.0", "style-loader": "^0.18.2", "webpack": "^3.0.0", "webpack-dev-middleware": "^1.12.0", "webpack-dev-server": "^2.9.1", "webpack-merge": "^4.1.0", "xml-loader": "^1.2.1" } }
明确mode:
许多引用库会根据process.env.NODE_ENV来决定包含什么。在非生产模式下许多库会添加一些额外的日志和测试来使调试更加简单。而在process.env.NODE_ENV==="production"时它们可能会删除或加入一部分重要的代码来提高真实用户运行你的代码时的性能。webpack v4及以后明确mode属性会自动帮你配置DefinePlugin插件:
webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
});
ps:技术上讲,NODE_ENV 是一个由 Node.js 暴露给执行脚本的系统环境变量。通常用于决定在开发环境与生产环境(dev-vs-prod)下,服务器工具、构建脚本和客户端 library 的行为。然而,与预期不同的是,无法在构建脚本 webpack.config.js 中,将 process.env.NODE_ENV 设置为 "production"。因此,例如 process.env.NODE_ENV === 'production' ? '[name].[hash].bundle.js' : '[name].bundle.js' 这样的条件语句,在 webpack 配置文件中,无法按照预期运行。
如果你使用了像react这样的库,那你添加完这个插件后应该能发现输出包的大小减小了非常多。而且本地src文件夹下的文件都会识别这个变量,所以以下检查会有效:
src/index.js
import { cube } from './math.js';
+
+ if (process.env.NODE_ENV !== 'production') {
+ console.log('Looks like we are in development mode!');
+ }
function component() {
var element = document.createElement('pre');
element.innerHTML = [
'Hello webpack!',
'5 cubed is equal to ' + cube(5)
].join('\n\n');
return element;
}
document.body.appendChild(component());
压缩:
注意,虽然UglifyJSPlugin 是代码压缩方面比较好的选择,但是还有一些其他可选择项。以下有几个同样很受欢迎的插件:
BabelMinifyWebpackPluginClosureCompilerPlugin
如果决定尝试以上这些,只要确保新插件也会按照Tree Shaking指南中所陈述的,具有删除未引用代码(dead code)的能力足矣。
Source Mapping:
我们鼓励你在生产环境中启用 source map,因为它们对调试源码(debug)和运行基准测试(benchmark tests)很有帮助。也就是说,你应该选择一个针对生产环境的构建速度较快的配置。对于本指南,我们将在生产环境中使用 source-map 选项,而不是我们在开发环境中用到的 inline-source-map:
webpack.prod.js
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production',
+ devtool: 'source-map'
});
ps:避免在生产中使用 inline-*** 和 eval-***,因为它们可以增加 bundle 大小,并降低整体性能。
Split CSS:
正如在管理资源中最后的 加载CSS小节中所提到的,通常最好的做法是使用 ExtractTextPlugin 将 CSS 分离成单独的文件。在插件文档中有一些很好的实现例子。disable 选项可以和 --env 标记结合使用,以允许在开发中进行内联加载,推荐用于热模块替换和构建速度。
CLI替代选项:
以上描述也可以通过命令行实现。例如,--optimize-minimize 标记将在后台引用 UglifyJSPlugin。和以上描述的 DefinePlugin 实例相同,--define process.env.NODE_ENV="'production'" 也会做同样的事情。并且,webpack -p 将自动地调用上述这些标记,从而调用需要引入的插件。
这些简便方式虽然都很不错,但是我们通常建议只使用配置方式,因为在这两种场景中下,配置方式能够更好地帮助你了解自己正在做的事情。配置方式还可以让你更方便地控制这两个插件中的其他选项。
出处:https://www.cnblogs.com/suqin-marker/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利。

浙公网安备 33010602011771号