webpack 文档(指南)- 摇树优化

摇树优化,即打包编译的时候移除未使用的代码。但是有一个前提,我们编写的代码必须是基于 ES6 Module 的静态结构特性的。

以下是静态结构的代码。

import a from './a';
import b from './b';
export default a;

以下是非静态结构的代码。

console.log('index.js');
const flag = Math.random();
if (flag) {
    module.exports = 1;
} else {
    module.exports = {};
}

if (flag) {
    require('./a.js');
} else {
    require('./b.js');
}

准备 demo

unused.js

const a = 1;
const b = () => {
    return 'test.js';
}
export {a, b};

math.js

export function add(a, b) {
    return a + b;
}
export function sub(a, b) {
    return a - b;
}

inde.js

// 它包含了两个函数,只使用其中的一个函数
import {add} from './math';
// 只引入但未使用
import * as unused from './unused';

const result = add(55, 45);
console.log(result);

开发环境测试

webpack.config.js

var HtmlWebpackPlugin = require('html-webpack-plugin');
var {
    CleanWebpackPlugin
} = require('clean-webpack-plugin');
module.exports = {
    mode: 'development',
    entry: {
        index: './index.js',
    },
    output: {
        publicPath: '',
        path: __dirname +  '/dist',
        filename: '[name].js'
    },
    module: {
        rules: []
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: './index.html'
        }),
    ]
}

./dist/index.js (代码片段)

"./index.js":
(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval(`__webpack_require__.r(__webpack_exports__);\n
/* harmony import */ 
var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math */ \"./math.js\");\n
/* harmony import */ 
var _unused__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./unused */ \"./unused.js\");\n\r\n\r\n\r\n
const result = Object(_math__WEBPACK_IMPORTED_MODULE_0__[\"add\"])(55, 45);\r\n
console.log(result);\n\n
//# sourceURL=webpack:///./index.js?`);

}),

"./math.js":
(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval(`__webpack_require__.r(__webpack_exports__);\n
/* harmony export (binding) */
 __webpack_require__.d(__webpack_exports__, \"add\", function() { return add; });\n
 /* harmony export (binding) */ 
 __webpack_require__.d(__webpack_exports__, \"sub\", function() { return sub; });\n
 function add(a, b) {\r\n    return a + b;\r\n}\r\n
 function sub(a, b) {\r\n    return a - b;\r\n}\n\n
 //# sourceURL=webpack:///./math.js?`);

}),

"./unused.js":
(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval(`__webpack_require__.r(__webpack_exports__);\n
/* harmony export (binding) */ 
__webpack_require__.d(__webpack_exports__, \"a\", function() { return a; });\n
/* harmony export (binding) */ 
__webpack_require__.d(__webpack_exports__, \"b\", function() { return b; });\n
const a = 1;\r\n
const b = () => {\r\n    
  return 'test.js';\r\n
}\r\n\n\n
//# sourceURL=webpack:///./unused.js?`);

})

发现默认情况下,webpack不会进行摇树优化。

webpack 的配置文件中加入 optimization.usedExports 的配置(可以对代码做一些注释标记,方便其他优化工具或代码使用,如标记未使用的代码)。

webpack.cofig.js

var HtmlWebpackPlugin = require('html-webpack-plugin');
var {
    CleanWebpackPlugin
} = require('clean-webpack-plugin');
module.exports = {
    mode: 'development',
    entry: {
        index: './index.js',
    },
    optimization: {
        usedExports: true
    },
    output: {
        publicPath: '',
        path: __dirname +  '/dist',
        filename: '[name].js'
    },
    module: {
        rules: []
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: './index.html'
        }),
    ]
}

./dis/index.js (代码片段)

"./index.js":
(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval(`__webpack_require__.r(__webpack_exports__);\n
/* harmony import */ 
var _math__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./math */ \"./math.js\");\n
/* harmony import */ 
var _unused__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./unused */ \"./unused.js\");\n\r\n\r\n\r\n
const result = Object(_math__WEBPACK_IMPORTED_MODULE_0__[/* add */ \"a\"])(55, 45);\r\n
console.log(result);\n\n
//# sourceURL=webpack:///./index.js?`);

}),

"./math.js":
(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval(`/* harmony export (binding) */ 
__webpack_require__.d(__webpack_exports__, \"a\", function() { return add; });\n
/* unused harmony export sub */\n
function add(a, b) {\r\n    return a + b;\r\n}\r\n
function sub(a, b) {\r\n    return a - b;\r\n}\n\n
//# sourceURL=webpack:///./math.js?`);

}),

"./unused.js":
(function(module, __webpack_exports__, __webpack_require__) {

"use strict";
eval(`
/* unused harmony export a */\n
/* unused harmony export b */\n
const a = 1;\r\n
const b = () => {\r\n    return 'test.js';\r\n}\r\n\n\n
//# sourceURL=webpack:///./unused.js?`);

})

在开发环境下,如果配置了 optimization.usedExportstrue ,那么会标记未使用的代码,但并不会真正的去删除它们,如果要删除这些未使用的代码,需要配置为生产环境。

在这里插入图片描述

生产环境测试

webpack.config.js

var HtmlWebpackPlugin = require('html-webpack-plugin');
var {
    CleanWebpackPlugin
} = require('clean-webpack-plugin');
module.exports = {
    mode: 'production',
    entry: {
        index: './index.js',
    },
    output: {
        publicPath: '',
        path: __dirname +  '/dist',
        filename: '[name].js'
    },
    module: {
        rules: []
    },
    plugins: [
        new CleanWebpackPlugin(),
        new HtmlWebpackPlugin({
            template: './index.html'
        }),
    ]
}

./dis/index.js

! function (e) {
    var t = {};

    function n(r) {
        if (t[r]) return t[r].exports;
        var o = t[r] = {
            i: r,
            l: !1,
            exports: {}
        };
        return e[r].call(o.exports, o, o.exports, n), o.l = !0, o.exports
    }
    n.m = e, n.c = t, n.d = function (e, t, r) {
        n.o(e, t) || Object.defineProperty(e, t, {
            enumerable: !0,
            get: r
        })
    }, n.r = function (e) {
        "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(e, Symbol.toStringTag, {
            value: "Module"
        }), Object.defineProperty(e, "__esModule", {
            value: !0
        })
    }, n.t = function (e, t) {
        if (1 & t && (e = n(e)), 8 & t) return e;
        if (4 & t && "object" == typeof e && e && e.__esModule) return e;
        var r = Object.create(null);
        if (n.r(r), Object.defineProperty(r, "default", {
                enumerable: !0,
                value: e
            }), 2 & t && "string" != typeof e)
            for (var o in e) n.d(r, o, function (t) {
                return e[t]
            }.bind(null, o));
        return r
    }, n.n = function (e) {
        var t = e && e.__esModule ? function () {
            return e.default
        } : function () {
            return e
        };
        return n.d(t, "a", t), t
    }, n.o = function (e, t) {
        return Object.prototype.hasOwnProperty.call(e, t)
    }, n.p = "", n(n.s = 0)
}([function (e, t, n) {
    "use strict";
    n.r(t);
    const r = function (e, t) {
        return e + t
    }(55, 45);
    console.log(r)
}]);

在生产模式下,webpack 对代码已经做了极致优化,发现未使用的代码都不见了。。

sideEffects

sideEffects 指的是有副作用的代码,假如模块 A 中包含一些影响全局作用域(非模块作用域)的代码,如改变了全局的变量或对象的变量(例如一些 polyfill ),模块 B 引入了模块 A ,但只使用它的部分导出或根本没有使用它的导出。在这种情况下,模块 A 就被认为是有副作用的,webpack 是不会删除模块 A 中所有未使用的代码的,它还会保留模块 A 中立即执行并对全局环境有影响的代码!

math.js

export function add(a, b) {
    return a + b;
}
export function sub(a, b) {
    return a - b;
}
// 副作用的代码,修改了全局的东西,会被保留
Number.prototype.add = add;

如果项目中所有模块都不会有副作用,那么可以在 webpack 的配置中将 optimization.sideEffects 设为 false ,这样可以提高删除未使用代码的编译速度。如果有某些模块是有副作用的,那么可以将它的路径加入 package.jsonsideEffects 数组选项中,这样也能提高删除未使用代码的速度。

package.json

{
  "name": "webpack",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "webpack"
  },
  "sideEffects": [
    "./math.js"
  ]
}

当然,sideEffects 这个选项不是必须要配置的!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值