webpack 如何优雅的使用tree-shaking

1.什么是tree-shaking

webpack 2 的到来带来的最棒的新特性之一就是tree-shaking 。tree-shaking源自于rollup.js,先如今,webpack 2也有类似的做法。

webpack 里的tree-shaking的到来不得不归功于es6规范的模块。为什么这么说,如今的前端模块规范很多,比较出流行的比如commonJS , AMD , es6 ,我简单的说一下commonJS和es6模块的区别。


commonJS 模块

commonJS的模块规范在Node中发扬光大,总的来说,它的特性有这几个:

1.动态加载模块
commonJS和es6的最大区别大概就在于此了吧,commonJS模块的动态加载能够很轻松的实现懒加载,优化用户体验。

2.加载整个模块
commonJS模块中,导出的是整个模块。

3.每个模块皆为对象
commonJS模块都被视作一个对象。

4.值拷贝
commonJS的模块输出和 函数的值传递相似,都是值的拷贝

es6 模块

1.静态解析
即在解析阶段就确定输出的模块,所以es6模块的import一般写在被引入文件的开头。

2.模块不是对象
在es6里,每个模块并不会当做一个对象看待

3.加载的不是整个模块
在es6模块中经常会看见一个模块中有好几个export 导出

4.模块的引用
es6模块中,导出的并不是模块的值拷贝,而是这个模块的引用


在结合es6模块和commonJS模块的区别之后,我们知道es6的特点是静态解析,而commonJS模块的特点是动态解析的,因此,借于es6模块的静态解析,tree-shaking的实现才能成为可能。
在webpack中,tree-shaking指的就是按需加载,即没有被引用的模块不会被打包进来,减少我们的包大小,缩小应用的加载时间,呈现给用户更佳的体验。

2.怎么使用tree-shaking

说了这么多那到底如何使用tree-shaking呢?
webpack默认es6规范编写的模块都能使用tree-shaking。这是什么意思呢?下面来看个例子。
首先奉上我的demo目录如下:

├─dist└─index.html
├─node_modules└─...
├─src├─scripts├─assets
├─webpack.config.js
└─package.json

dist用来存放打包好的代码
src相反的用来存放源文件
src里的scripts目录用来存放js脚本文件,assets用来存放静态资源文件

以下几条命令过后开始我们的tree-shaking之旅

npm install --save-dev webpack webpack-dev-server

webpack.config.js

const webpack = require('webpack')
const path = require('path')module.exports = {entry:'./src/scripts/main.js',output:{path:path.resolve(__dirname,'dist/'),filename:'main.bundle.js'},plugins:[new webpack.HotModuleReplacementPlugin()],devServer:{port:4200,contentBase:path.resolve(__dirname,'dist/'),historyApiFallback:true,hot:true}
}

接下来是main.js,直接引入了sayHello

import { sayHello } from './greeter.ts';sayHello();

相应的main.js的依赖greeter.js

export function sayHello(){alert('hello')
}export function sayWorld(){alert('world')
}

在dist目录下有个index.html 用来引入打包后的bundle

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Document</title>
</head>
<body><script type="text/javascript" src="./main.bundle.js"></script>
</body>
</html>

以上就是整个demo的代码,接下来的事情我们直接webpack打包试试看

webpack

去掉打包后冗长的代码(如果对打包后的代码有兴趣的可以移步我的另一篇博文http://blog.csdn.net/haodawang/article/details/77126686),只看chunk传参的部分:

[
/* 0 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__person__ = __webpack_require__(1);Object(__WEBPACK_IMPORTED_MODULE_0__person__["a" /* sayHello */])();/***/ }),
/* 1 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return sayHello; });
/* unused harmony export sayWorld */function sayHello(){alert('hello');}function sayWorld(){alert('world');}/***/ })
/******/ ]

我们关注这一行

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

实际上只return了一个sayHello。
因此我们现在只需要压缩一下整个Js代码,就能把没引用的sayWorld剔除。

键入以下命令进行压缩

webpack --optimize-minimize

由于压缩后的代码只有一行了,我们移步尾部:

function(e,n,r){"use strict";function t(){alert("hello")}r.d(n,"a",function(){return t})}]);

可以看到sayWorld函数已经被成功剔除。

我们启动webpack-dev-server

webpack-dev-server

在浏览器中输入

http://localhost:4200

每次都需要在命令行里输入参数,岂不是很麻烦,还有没有其他更好的办法呢?

(1)我们可以把这串命令放入package.json的scripts字段,然后通过npm start来自动执行

(2)其实–optimize-minimize的底层实现是一个插件UglifyJsPlugin,因此,我们可以直接在webpack.config.js里配置它

在webpack.config.js里配置插件

const path = require('path');
const webpack = require('webpack');module.exports = {entry:'./src/scripts/main.js',output:{filename:'main.bundle.js',path:path.join(__dirname,'dist')},plugins:[new webpack.optimize.UglifyJsPlugin(), // <----------- 压缩jsnew webpack.HotModuleReplacementPlugin()],devServer:{port:4200,historyApiFallback:true,hot:true,contentBase:path.join(__dirname,"dist/")}
}

然后我们webpack打包

webpack

即看到同样的效果

function(e,n,r){"use strict";function t(){alert("hello")}r.d(n,"a",function(){return t})}]);

在tree-shaking触发打包后,仅仅是撇开了模块的引用,但还是要结合压缩工具来进行,这才是完整的一次tree-shaking

那如果是typescript该怎么使用tree-shaking呢?

3.如何在typescript里使用tree-shaking

要在webpack里使用ts,首先我们必须安装tsc

npm install --save-dev typescript

之后我们需要解析ts文件的loader

npm install --save-dev ts-loader

然后在webpack.config.js进行配置

const webpack = require('webpack')
const path = require('path')module.exports = {entry:'./src/scripts/main.ts',output:{path:path.resolve(__dirname,'dist/'),filename:'main.bundle.js'},module:{rules:[{test:/\.ts$/,use:['ts-loader']}]},plugins:[new webpack.optimize.UglifyJsPlugin(),new webpack.HotModuleReplacementPlugin()],devServer:{port:4200,contentBase:path.resolve(__dirname,'dist/'),historyApiFallback:true,hot:true}
}

献上我的两份文件main.ts , greeter.ts (这两份文件除了后缀名基本没有改动)

main.ts

import { sayHello } from './greeter.ts';sayHello();

greeter.ts

export var sayHello = function(){alert('hello')
}export var sayWorld = function(){alert('world')
}

之后我们需要做的是,创建一个tsconfig.json的配置文件供tsc解析,这时,坑来了。

下面是我的tsconfig.json文件

{"compilerOptions":{"target":"es5","sourceMap":true},"exclude":["./node_modules"]
}

好像没有什么不对

接着我们webpack

webpack

看下打包压缩后的代码的最后一部分:

"use strict";Object.defineProperty(n,"__esModule",{value:!0}),n.sayHello=function(){alert("hello")},n.sayWorld=function(){alert("world")}}]);

sayWorld居然还是存在!!!怎么回事,为什么没有被触发tree-shaking优化?

这是因为tsc编译后的代码为es5 ,而正因如此,tsc默认使用了commonJS的规范来加载模块,因此并没有触发tree-shaking,那我们要怎么做?

修改一下tsconfig.json,把target改为es6即可!

{"compilerOptions":{"target":"es6","sourceMap":true},"exclude":["./node_modules"]
}

再次打包

webpack

看一下打包后的bundle

function(e,n,r){"use strict";r.d(n,"a",function(){return t});var t=function({alert("hello")}}]);

果然是触发了tree-shaking

开启webpack-dev-server

webpack-dev-server

可以看到成功打印hello

以上就是我对webpack tree-shaking的总结,希望对大家的学习有所帮助

webpack 如何优雅的使用tree-shaking(摇树优化)相关推荐

  1. tree shaking(摇树优化)

    tree shaking(摇树优化) 前言 随着js的不断发展,性能优化成了主流的方向,但是如何性能优化又成了现在程序员的一大苦恼,而我作为一名前端小白,也就深陷其中,最近学习到了tree shaki ...

  2. Angular 应用里的摇树优化 - tree shaking

    Tree Shakeable Providers and Services in Angular Angular 最近推出了一项新功能,Tree Shakeable Providers. Tree S ...

  3. Webpack进阶(一) tree shaking与不同mode

    Tree Shaking 生产环境去除没有使用到的内容(开发环境没有删除,会影响调试) 只支持ESM规范(静态引入,编译时引入),不支持CJS(动态引入,执行时引入) // webpack.confi ...

  4. 手写小程序摇树优化工具(三)——遍历json文件

    见素包朴,少私寡欲,绝学无忧 github: miniapp-shaking 上一章我们介绍了遍历js文件的方法,接下来我们介绍其他文件的遍历. 1. 遍历JSON文件 对于json文件,我们直接读取 ...

  5. webpack中的tree shaking(树摇)-----移除未使用的代码

    本篇大致概括一下tree shaking的作用以及与webpack相结合使用 什么是tree shaking 引用webpack官网的原文来说: tree shaking 是一个术语,通常用于描述移除 ...

  6. webpack构建中tree shaking、scope Hoisting(面试题)

    一.tree shaking (摇树优化) tree shaking概念: 1个模块可能有多个方法,只要其中某个方法使用了,整个文件会被打到bundle中 tree shaking 只将用到的方法打到 ...

  7. Tree Shaking概念详解

    这篇文章写于两年前,前端的发展日新月异,新的构建工具已经开始崭露头角.Vite已经出来很久了,新版本也比较稳定,推荐大家学习这一款构建工具. Tree Shaking 指的就是当我引入一个模块的时候, ...

  8. Tree Shaking和DCE

    Tree Shaking和DCE Tree Shaking 指的就是当我引入一个模块的时候,我不引入这个模块的所有代码,我只引入我需要的代码,这就需要借助 webpack 里面自带的 Tree Sha ...

  9. dce和tree shaking

    dce和tree shaking 为了在弱网环境下降低网络延迟以获取更好的用户体验,我想这些关于如何降低代码体积的技术都是值得研究的.目前降低网络延迟的一个方法是降低js代码的体积,本文研究的就是在压 ...

最新文章

  1. TOJ--3456--数学题
  2. 2015.11.11
  3. 旷视 IPO 在即,看清“AI 第一股”的商业真相
  4. 存储系统的类型及特点
  5. [转载]ASP.NET Core 源码阅读笔记(1) ---Microsoft.Extensions.DependencyInjection
  6. 5、【华为HCIE-Storage】--RAID类型
  7. 十分钟学习nginx
  8. 七、深入JavaScript的DOM(三)
  9. mysql count 排序_SQL进阶排序和窗口函数
  10. LeetCode 695. 岛屿的最大面积(图的BFS/DFS)
  11. html调用xfplugin,使用多设备执行脚本的时候,html report功能无法正常使用
  12. python动态执行语句_Python Language
  13. 使用C#读取XML节点,修改XML节点
  14. 手机网站的图片轮换教程
  15. 优化性能一点总结,供大家参考
  16. 迅雷“应版权方要求,文件无法下载”完美解决方法!
  17. 悟空CRM系统学习心得
  18. (P24)进程间通信介绍二:死锁 ,信号量与PV原语 ,用PV原语解决司机与售票员问题 ,用PV原语解决民航售票问题 ,用PV原语解决汽车租赁问题
  19. 12.flowable 流程实例 终止流程
  20. Oracle Spatial中上载GIS空间数据方法研究

热门文章

  1. 基于微信小程序的移动学习平台的设计与实现_kaic
  2. pycharm 字体放大与缩小
  3. 数据库连接由PgSQL转为Oracle的数据源配置
  4. Day02 每日英语
  5. 优惠券设计:优惠券的发放与使用
  6. 6-2 顺序表基本操作 (10 分)
  7. 前端本地模糊搜索并高亮
  8. win10家庭版调出组策略_Windows 10家庭版升级专业版
  9. CPU和内存 程序(线程)关系
  10. LoadIcon(),加载系统图标说明