之前介绍过webpack3的新特性,里面提到webpack2支持了ES6的import和export,不需要将ES6的模块先转成CommonJS模块,然后再进行打包处理。正基于此,webpack2引入了tree-shaking技术,能够在模块的层面上做到打包后的代码只包含被引用并被执行的模块,而不被引用或不被执行的模块被删除掉,以起到减包的效果。

webpack的tree-shaking案例

下面结合实际代码来解释webpack2是如何实现tree-shaking的,示例代码可到github进行下载

示例代码结构如图:src中index.js为入口文件,module.js是测试的模块文件,dist中是产出的文件。

根据webpack官网的提示,webpack支持tree-shaking,需要修改配置文件,指定babel处理js文件时不要将ES6模块转成CommonJS模块,具体做法就是:

在.babelrc设置babel-preset-es2015的modules为fasle,表示不对ES6模块进行处理。

// .babelrc文件
{
"presets": [
["es2015", { "modules": false }]
],
"comments": false
}

在webpack.config.js中设置babel-preset-es2015的modules为fasle,表示不对ES6模块进行处理。  

// webpack.config.js
...
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
["es2015", { "modules": false }]
]
}
}
]
...  

然后在module.js文件中创建三个模块sayHello,sayBye,sayHi,并在index.js引用sayHello,sayHi;

// module.js
export const sayHello = name => `Hello ${name}!`;
export const sayBye = name => `Bye ${name}!`;
export const sayHi = name => `Hi ${name}!`;

  

// index.js
import { sayHello } from './module';
import { sayHi } from './module';
const element = document.createElement('h1');
element.innerHTML = sayHello('World') + sayHi('my friend');
document.body.appendChild(element);

  

然后在当前目录执行 webpack 命令后,产出bundle.js的代码如下

/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return sayHello; });
/* unused harmony export sayBye */
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return sayHi; });
var sayHello = function sayHello(name) {
return "Hello " + name + "!";
};
var sayBye = function sayBye(name) {
return "Bye " + name + "!";
}; var sayHi = function sayHi(name) {
return "Hi " + name + "!";
}; /***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) { "use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__module__ = __webpack_require__(0);
var element = document.createElement('h1');
element.innerHTML = Object(__WEBPACK_IMPORTED_MODULE_0__module__["a" /* sayHello */])('World') + Object(__WEBPACK_IMPORTED_MODULE_0__module__["b" /* sayHi */])(' to meet you');
document.body.appendChild(element); /***/ })

  

从上面可以知道,sayBye模块被打上了unused harmony export标签,sayHello和sayHi被设置为__webpack_exports__的属性,在入口文件中通过读取__webpack_exports__的属性取出。

bundle.js文件虽然对多余的模块进行了标记,但是并没有删除,这是因为webpack还没有执行压缩混淆操作,可以通过webpack -p命令对产出进行压缩处理,这时候会把打了unused harmony export 标签的模块删除掉。

webpack的tree-shaking的局限性

(1)只能是静态声明和引用的ES6模块,不能是动态引入和声明的;

在打包阶段对冗余代码进行删除,就需要webpack需要在打包阶段确定模块文件的内部结构,而ES模块的引用和输出必须出现在文件结构的第一级('import' and 'export' may only appear at the top level),否则会报错。

// webpack编译时会报错
if (condition) {
import module1 from './module1';
} else {
import module2 from './module2';
}

  

而CommonJS模块支持动态结构的,所以不能对CommonJS模块进行tree-shaking处理。

(2)只能处理模块级别,不能处理函数级别的冗余;

因为webpack的tree-shaking是基于模块间的依赖关系,所以并不能对模块内部自身的无用代码进行删除。

(3)只能处理JS相关冗余代码,不能处理CSS冗余代码。

目前webpack只对JS文件的依赖进行了处理,CSS的冗余并没有给出很好的工具。最近听了一个讲座,提到了webpack-css-treeshaking-plugin,该插件基于AST对CSS冗余代码进行了很好的处理。

webpack中tree-shaking技术介绍的更多相关文章

  1. Webpack 4 Tree Shaking 终极优化指南

    几个月前,我的任务是将我们组的 Vue.js 项目构建配置升级到 Webpack 4.我们的主要目标之一是利用 tree-shaking 的优势,即 Webpack 去掉了实际上并没有使用的代码来减少 ...

  2. webpack使用tree shaking的问题。及关于UglifyJs不支持ES6的解决方案。

    webpack: plugins:[ new webpack.optimize.UglifyJsPlugin({ compress:{warning:true} }) ] 是的,一些dead code ...

  3. Webpack 的 Tree Shaking

    为什么要使用 Tree Shaking? 当从某文件模块中导出(某一个或几个变量.函数.对象等),然而这个文件模块还有许多其它(我们这次并不需要)的导出,webpack会不管三七二十一简单粗暴的将整个 ...

  4. 深入研究webpack之Tree Shaking相关属性sideEffects用处

    Tree Shaking我原来也只是了解,这次碰巧深入研究了下,就写个博客记录一下,网上有很多讲Tree Shaking的,我写的这篇跟他们侧重点不一样 Tree Shaking相关的基础知识 1 w ...

  5. [Webpack 2] Tree shaking with Webpack 2

    The less code you can send to the browser, the better. The concept of tree shaking basically says th ...

  6. webpack和tree shaking和rollup

    http://blog.csdn.net/haodawang/article/details/77199980 tree shaking只对es模块生效,在打包tyscript模块是要使用tsc编译器 ...

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

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://wanago.io/2018/08/13/webpack-4-course-part ...

  8. webpack(6)-模块热替代&tree shaking

    模块热替换(hot module replacement 或 HMR) 模块热替换(hot module replacement 或 HMR)是 webpack 提供的最有用的功能之一.它允许在运行时 ...

  9. 配置Tree Shaking来减少JavaScript的打包体积

    译者按: 用Tree Shaking技术来减少JavaScript的Payload大小 原文: Reduce JavaScript Payloads with Tree Shaking 译者: Fun ...

  10. Webpack 中的 Tree Shaking

    Tree Shaking Tree shaking 用于描述移除JavaScript上下文中的未引用代码(dead-code). 为了更方便地理解tree shaking,我们可以将应用程序想象成一棵 ...

随机推荐

  1. Session详解及集群共享

    Session的介绍 维基百科:会话(session)是一种持久网络协议,在用户(或用户代理)端和服务器端之间创建关联,从而起到交换数据包的作用机制,session在网络协议(例如telnet或FTP ...

  2. 前端魔法堂——异常不仅仅是try/catch

    前言  编程时我们往往拿到的是业务流程正确的业务说明文档或规范,但实际开发中却布满荆棘和例外情况,而这些例外中包含业务用例的例外,也包含技术上的例外.对于业务用例的例外我们别无它法,必须要求实施人员与 ...

  3. 谢欣伦 - 原创教程 - 使用GDI+绘制抗锯齿斜线

    早些年用过GDI的同学都知道,用GDI绘图API函数画斜线那个锯齿有多恶心.就像下图第一行的三条斜线: 坦白说,45度斜线在抗锯齿以前还是蛮抗锯齿的,哈哈,抗不抗都没什么差别. 那第二行很自然就看得出 ...

  4. IIC协议建模——读写EEPROM

    案例采用明德扬设计思想完成.IIC协议是非常常用的接口协议,在电子类岗位招聘要求中经常出现它的身影.关于IIC协议这里只做简要介绍,详细信息请自行百度或查阅相关Datasheet,网上资料非常多.该篇 ...

  5. LeetCode 73. Set Matrix Zeros(矩阵赋零)

    Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in place. click ...

  6. JavaAPI 中 <E> 与 <T> 的含义

    今天看集合的代码,发现在泛型的使用时的区别,Collection<E>.List<E>,而Iterator<T>,那么<E>和<T>含义有什 ...

  7. Java基础——字符串构建器

    StringBuilder类: 可以将许多小段的字符串构建一个字符串. StringBuilder builder = new StringBuilder(); //构造一个空的字符串构建器 buil ...

  8. MAC 下虚拟主机的配置

    第一部分:httpd.conf 1:找到这段,改成如下这样 <Directory /> Options Indexes FollowSymLinks AllowOverride All O ...

  9. stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结

    stl中auto_ptr,unique_ptr,shared_ptr,weak_ptr四种智能指针使用总结 1. auto_ptrauto_ptr主要是用来解决资源自动释放的问题,比如如下代码:voi ...

  10. Leetcode题解(25)

    77. Combinations 题目 分析:求给定数字n,k的组合数,方法是采用深度搜索算法,代码如下(copy网上代码) class Solution { public: void dfs77(v ...