专栏首页葡萄城控件技术团队Webpack 4教程 - 第七部分 减少打包体积与Tree Shaking

Webpack 4教程 - 第七部分 减少打包体积与Tree Shaking

在本次Webpack 4教程中,我们会更进一步讲述项目优化。我们会学习什么是tree shaking以及如何使用它。你会找到让Webpack 4中tree shaking运作起来所需要的东西,并知道怎样从中受益。开始吧!

首先,让我们来回答什么是tree shaking以及它带来什么好处。我们常常在文件中使用具名引入(named imports),这些引入的文件里有其他导出(exports)。在某些情况下,我们并没有引入所有的导出,但Webpack仍会把整个模块都导入进来。这种情况下就需要使用tree shaking了,因为它能帮助我们去除掉用不到的代码。因此打包后的体积能显著下降。

为了让tree shaking起作用,你需要满足一些配置要求。首先,必须使用ES 6模块,而不是使用诸如CommonJS的模块处理方式。如果你在使用Babel,这一点可能已让你遇到麻烦了。因为Babel的预置默认把任何模块转译成CommonJS模块。你可以简单设置modules: false来解决此问题,在.babalrc或者webpack.config.js中设置都可以。

.babelrc

{

  "presets": [

    ["env",

      {

        "modules": false

      }

    ]

  ]

}

// webpack.config.js

module: {

  rules: [

    {

      test: /\.js$/,

        exclude: /(node_modules)/,

          use: {

            loader: 'babel-loader',

            options: {

              presets: ['env', { modules: false }]

            }

          }

    }

  ]

},

你需要使用UglifyJsPlugin。默认情况下,它在mode: "produnction"是被启用。如果你倾向于不使用mode: "produnction",你可以手动添加UglifyJsPlugin

还有一件记得做的事情是,你需要打开optimization.usedExports。它同样在mode: "produnction"时被默认添加上去了。它告诉Webpack去决定每一个模块所用到的导出。有了它,Webpack会在你的打包产出里添加额外的像是/* unused harmony export */之类的注释,UglifyJsPlugin在之后会使用到它们。

Harmony是ES6和ES2015的代号。

让我们来研究有关例子。

// utilities.js

export function add(a, b) {

  return a + b;

}

 

export function subtract(a, b) {

  return a - b;

}

// index.js

import { add } from './utilities';

 

console.log(add(1,2));

console.log(add(3,4));

以正常配置运行Webpack,我们得到像下面这样的输出:

/*(...)*/

 

/* 1 */

/***/ (function(module, __webpack_exports__, __webpack_require__) {

 

"use strict";

__webpack_require__.r(__webpack_exports__);

/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "add", function() { return add; });

/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "substract", function() { return substract; });

function add(a, b) {

  return a + b;

}

function subtract(a, b) {

  return a - b;

}

 

/***/ })

/******/ ]);

正如你看到的,Webpack没有对我们的打包输出进行tree-shaking。这里同时有addsubtract方法。我们来试验一下,使用下面的配置:

// webpack.config.js

const webpack = require('webpack');

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

const UglifyJS = require('uglify-es');

 

const DefaultUglifyJsOptions = UglifyJS.default_options();

const compress = DefaultUglifyJsOptions.compress;

for(let compressOption in compress) {

  compress[compressOption] = false;

}

compress.unused = true;

 

module.exports = {

  mode: 'none',

  optimization: {

    minimize: true,

    minimizer: [

      new UglifyJsPlugin({

        uglifyOptions: {

          compress,

          mangle: false,

          output: {

            beautify: true

          }

        },

      })

    ],

  }

}

我已经关掉了大部分UglifyJsPlugin的配置,以便于我们清楚地看到我们的代码发生了什么。使用上面的配置运行,得到下面输出:

/* (...) */

 

/* 0 */

/***/ function() {

  "use strict";

  // CONCATENATED MODULE: ./src/utilities.js

  function add(a, b) {

    return a + b;

  }

  // CONCATENATED MODULE: ./src/index.js

  console.log(add(1, 2));

  console.log(add(3, 4));

  /***/}

/******/ ]);

由于使用了UglifyJsPluginoptimization.usedExportsunused选项,不需要的代码被移除了。请注意,那是UglifyJsPlugin的默认行为,所以使用默认配置也能去除无用的代码(当然这样还会进行其他压缩处理)。

Tree shaking函数库

如果你打算对函数库进行tree shaking,你需要记得上一段提到的是事情:使用ES6模块,而它并不是总是被函数库使用。一个绝佳的例子是lodash。如果你去看它提供的产品代码,可以清楚地看到它并没有使用ES6模块

试想我们打算使用lodash提供的debounce方法。

// index.js

import _ from 'lodash';

 

console.log(_.debounce);

现在你的输出里包含了整个lodash库。当使用import _ from 'lodash'时,这无法避免。但不要担心!有人已经思考过此问题,并创建了一个包叫做lodash-es。它以ES6模块的形式提供了lodash库。

import { debounce } from 'lodash';

 

console.log(debounce);

Webpac默认会忽略sideEffect标识。如果想改变这种行为,我们需要吧optimization.sideEffects设置成true。你可以手动设置,或者通过mode: "produnction"实现。

// webpack.config.js

const UglifyJsPlugin = require('uglifyjs-webpack-plugin');

const HtmlWebpackPlugin = require('html-webpack-plugin');

 

module.exports = {

  mode: 'none',

    optimization: {

      minimize: true,

      minimizer: [

        new UglifyJsPlugin()

      ],

      usedExports: true,

      sideEffects: true

    },

  plugins: [

    new HtmlWebpackPlugin()

  ]

}

现在lodash库能够被Webpack进行tree shaking了。

总结

为了使tree shaking起作用,需要满足许多条件。它是个很有用的特性,当然也值得学习。希望你通过本文了解如何使用它,让打包后的体积大幅减小。记住你需要使用ES6模块UglifyJsPlugin。另外,记得配置optimization,把usedExportssideEffects设为true。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 2017年 JavaScript 框架回顾 -- React生态系统

    前一篇文章中,我们介绍了2017年 JavaScript 框架的整体情况。我们也了解到在众多的前端框架中,目前最为庞大又在快速增长的当属 React 了,本文就...

    葡萄城控件
  • 实战使用Axure设计App,使用WebStorm开发(6) – 迈向后端

     系列文章 实战使用Axure设计App,使用WebStorm开发(1) – 用Axure描述需求 实战使用Axure设计App,使用WebStorm开发(2...

    葡萄城控件
  • 纯前端控件集 WijmoJS 2018V2发布,在React、Vue和Angular中更易用

    作为一款纯前端控件集,WijmoJS 秉承“快如闪电,触控优先”的设计理念,在提供优质服务和产品的同时,专注于企业应用开发,不断优化产品架构,与时俱进。除在全球...

    葡萄城控件
  • ext3支持的单个文件大小

    block size=1024时,单个文件最大支持16GB block size=4096时,单个文件最大支持4TB (官方说是2TB)

    py3study
  • 2014年最后一期腾讯T派校园开放日活动成功举办

    概 况 为了促进高校学生对腾讯的认识与了解,感受腾讯用心做产品的态度,提升腾讯在校园的品牌影响力,腾讯公司高校合作团队近年来在北京、成都、广州、深圳等地组织了...

    腾讯高校合作
  • 国际顶级行业研究机构发布:腾讯安全位居威胁情报服务市场领导者象限

    北京时间11月30日,《IDC MarketScape:中国威胁情报安全服务(TISS)市场,2018厂商评估》报告正式发布,腾讯凭借腾讯云覆盖“云管端”的智...

    腾讯云安全
  • javax.ws.rs.Path注解@Path的工作原理解析

    这个annotation和Spring里的@RequestMapping作用完全一样。下图是Spring里的annotation:

    Jerry Wang
  • iOS中URL编码那些事

    在iOS程序中,访问一些HTTP/HTTPS的资源服务时,如果url中存在中文或者特殊字符时,会导致无法正常的访问到资源或服务,想要解决这个问题,需要对url进...

    freesan44
  • 超融合详细对比:市面各主流超融合产品及厂商优劣势解密

    随着超融合在国内市场兴起并逐步成为主流,一场针对于IT基础架构的技术变革悄然而至。沿用二十多年的传统IT架构面临着新一代架构的严重冲击。近几年来,面对巨大的市场...

    钱曙光

扫码关注云+社区

领取腾讯云代金券