Webpack 4 教程 - 5. 生產模式下內建的優化

在本次教程中,咱們聚焦於如何在你的應用中減小輸出文件的體積,從而提高用戶體驗。這意味着在生產環境下要用不一樣的方式來處理代碼。今天咱們將闡述webpack經過mode參數來設置其內置的優化措施, 開始吧。javascript

Webpack 4教程:爲什麼優化代碼

首先,咱們回答究竟爲何要優化你的代碼這個問題。若是你有良好編程實踐,你可能注重代碼的可讀性,所以你在代碼中添加了大量的空白符(製表符、空格、換行符)和註釋。在代碼變得更漂亮的同時,也使得文件的體積大大增長了。另外一方面,爲了用戶體驗(指減小文件體積)而犧牲可讀性也不可取,手工這麼作的話很繁瑣。所以,這兒有一種解決方案供你在項目中選擇。java

Mode: production

Webpack4中引入了一個新參數:mode。要求老是在配置中指定。若是不指定,會產生一個警告並退而其次的使用默認值,默認值就是production。若是你使用 mode:"production", Webpack將配置成生成更適合在生產環境下的代碼。咱們如今就來看看webpack爲咱們確切地作了些什麼。webpack

UglifyJsPlugin插件

將mode值設爲production將在配置中添加UglifyJsPlugin插件,它經過壓縮和最小化,使得你的代碼更短,運行得更快。其任務包括簡單的縮短變量名,移除空白符,刪除重複代碼等等。默認會解析每個.js文件。這篇博文中,咱們將講述UglifyJSPlugin這個插件最基本的配置。即便webpack 4 依據選擇的mode值進行了優化,你仍能經過optimization屬性來進行本身的配置。git

// 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屬性。github

new UglifyJsPlugin({
    uglifyOptions: {
        compress: {
            /*(...)*/
        }
    }
})

它負責UglifyJsPlugin插件的不少重要的舉措,從而是你的代碼更短,更輕。完整列表請參閱官方文檔,其也標記出了默認值。web

UglifyJsPlugin插件另一個重要的屬性是output。編程

new UglifyJsPlugin({
    uglifyOptions: {
        compress: {
            /*(...)*/
        },
        output: {
            /*(...)*/
        }
    }
})

默認,代碼生成器試圖輸出最短的代碼。你能夠經過更改output的配置來改變這一行爲。你可能無需對默認值改動太多,但有一個值得考慮的屬性:drop_console,默認它的設置值是false。若是改成true,將刪除代碼中全部的console.log調用。若是想了解更多output的屬性,請查閱完整列表閉包

UglifyJsPlugin還有更多的可能的配置,請參讀它在Github上的文檔app

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能作的內置優化措施。這樣使得你的應用加載得更快,執行得更好。通過一系列的配置處理,達到如此目標,從而知足產品須要。下一個教程咱們將覆蓋開發模式下的配置,敬請期待!

相關文章
相關標籤/搜索