在本次教程中,我们聚焦于如何在你的应用中减少输出文件的体积,从而提升用户体验。这意味着在生产环境下要用不同的方式来处理代码。今天我们将阐述webpack通过mode参数来设置其内置的优化措施, 开始吧。
Webpack 4教程:为何优化代码
首先,我们回答究竟为什么要优化你的代码这个问题。如果你有良好编程实践,你可能注重代码的可读性,因此你在代码中添加了大量的空白符(制表符、空格、换行符)和注释。在代码变得更漂亮的同时,也使得文件的体积大大增加了。另一方面,为了用户体验(指减少文件体积)而牺牲可读性也不可取,手工这么做的话很繁琐。因此,这儿有一种解决方案供你在项目中选择。
Mode: production
Webpack4中引入了一个新参数:mode。要求总是在配置中指定。如果不指定,会产生一个警告并退而其次的使用默认值,默认值就是production。如果你使用 mode:"production", Webpack将配置成生成更适合在生产环境下的代码。我们现在就来看看webpack为我们确切地做了些什么。
UglifyJsPlugin插件
将mode值设为production将在配置中添加UglifyJsPlugin插件,它通过压缩和最小化,使得你的代码更短,运行得更快。其任务包括简单的缩短变量名,移除空白符,删除重复代码等等。默认会解析每一个.js文件。这篇博文中,我们将讲述UglifyJSPlugin这个插件最基本的配置。即使webpack 4 依据选择的mode值进行了优化,你仍能通过optimization属性来进行自己的配置。
// webpack.config.js
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
module.exports = {
mode: "production",
// using mode: "production" attaches the following configuration:
optimization: {
minimize: true,
minimizer: [
new UglifyJsPlugin()
]
},
}
传给UglifyJsPlugins插件最要紧的属性是uglifyOptions,它有大量默认的配置。而其中最值得关注的部分是compress属性。
new UglifyJsPlugin({
uglifyOptions: {
compress: {
/*(...)*/
}
}
})
它负责UglifyJsPlugin插件的很多重要的举措,从而是你的代码更短,更轻。完整列表请参阅官方文档,其也标记出了默认值。
UglifyJsPlugin插件另外一个重要的属性是output。
new UglifyJsPlugin({
uglifyOptions: {
compress: {
/*(...)*/
},
output: {
/*(...)*/
}
}
})
默认,代码生成器试图输出最短的代码。你可以通过更改output的配置来改变这一行为。你可能无需对默认值改动太多,但有一个值得考虑的属性:drop_console,默认它的设置值是false。如果改为true,将删除代码中所有的console.log调用。如果想了解更多output的属性,请查阅完整列表。
UglifyJsPlugin还有更多的可能的配置,请参读它在Github上的文档。
DefinePlugin插件
这个插件允许你创建全局常量用于编译时解析。如果设置mode:"production",webpack默认会设置"process.env.NODE_ENV": JSON.stringify("production")。
// webpack.config.js
module.exports = {
mode: "production",
// using mode: "production" attaches the following configuration:
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
}),
]
}
注意因为直接文本替换,所给的属性值必须包括引号,要这么做JSON.stringify("production")或'"production"'。
在编译时解析意味着你在代码中使用的process.env.NODE_ENV,将被替换成production这个值。
console.log(process.env.NODE_ENV);
if(process.env.NODE_ENV === 'production') {
console.log('this is production!')
}
记住,在webpack编译完代码之后就没有process.env.NODE_ENV这个常量值了。上面的代码在webpack处理之后变成下面的样子:
console.log("production");
if(true) {
console.log("this is production!")
}
在UglifyJSPlugin插件最小化处理之后,它更是简化为:
console.log("production");
console.log("this is production!")
NoEmitOnErrorsPlugin插件
使用这个插件将赞助你处理编译期间的错误。例如,可能出现你试图导入一个webpack不能解析(译注:就是找不到啦)的文件的情形。此时,Webpack会创建一个有错误信息的新版应用。如果使用NoEmitOnErrorsPlugin,就根本不会创建这个版本。
(译注:原文是这样子的:
Using this plugin will help you deal with errors during the compilation. For example, there might be a situation in which you try to import a file that Webpack can’t resolve. In this situation, Webpack creates a new version of the application with the information about the error. With the usage of NoEmitOnErrorsPlugin, this version is not created at all.
是不是说得云里雾里?其实意思是,如果没有使用NoEmitOnErrorsPlugin,当发生错误时,就会重载一个有错误信息的页面,把用户的屏幕搞花。使用NoEmitOnErrorsPlugin插件,就不会加载这个页面了,错误信息只是在控制台中输出)
// webpack.config.js
const webpack = require('webpack');
module.exports = {
mode: "production",
// using mode: "production" attaches the following configuration:
plugins: [
new webpack.NoEmitOnErrorsPlugin();
]
}
ModuleConcatenationPlugin插件
Webpack默认将每一个模块包装在独立的闭包函数中,这个包装函数使得javascript的执行稍微变慢了一点。看看下面的例子:
// one.js
const dog = 'Fluffy';
export const one = 1;
// two.js
const dog = 'Fluffy';
export const two = 2;
// index.js
import { one } from './one';
import { two } from './two';
const dog = 'Fluffy';
console.log(one, two);
如没有ModuleConcatenationPlugin插件,输出的打包象这个样子:
// main.js
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _one__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var _two__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
const dog = 'Fluffy';
console.log(_one__WEBPACK_IMPORTED_MODULE_0__["one"], _two__WEBPACK_IMPORTED_MODULE_1__["two"]);
/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "one", function() { return one; });
const dog = 'Fluffy';
const one = 1;
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "two", function() { return two; });
const dog = 'Fluffy';
const two = 2;
/***/ })
/******/ ]);
当设置mode为production,ModuleConcatenationPlugin插件就会尽心尽责。谢天谢地,现在输出的打包在一个作用域里了。更少的函数意味着更少的运行时开销。
注意,这个例子中我没有进行任何缩小化。由于缩小化器现在知道了模块间的依赖,它能更好的干活。
// main.js
(function(module, __webpack_exports__, __webpack_require__) {
"use strict";
// CONCATENATED MODULE: ./src/one.js
const dog = 'Fluffy';
const one = 1;
// CONCATENATED MODULE: ./src/two.js
const two_dog = 'Fluffy';
const two = 2;
// CONCATENATED MODULE: ./src/index.js
const src_dog = 'Fluffy';
console.log(one, two);
/***/ })
/******/ ]);
如果你觉得有趣,请阅读article on the webpack blog上针对这一特性的博文。
小结
今天我们学习了配置mode:'production'时Webpack能做的内置优化措施。这样使得你的应用加载得更快,执行得更好。经过一系列的配置处理,达到如此目标,从而满足产品需要。下一个教程我们将覆盖开发模式下的配置,敬请期待!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。