乐趣区

关于前端:jsliang-求职系列-33-Webpack-Tree-Shaking

一 目录

不折腾的前端,和咸鱼有什么区别

目录
一 目录
二 前言
三 什么是 dead-code
四 什么是副作用?
五 如何做到 Tree Shaking
六 总结
七 其余问题
 7.1 发问 1:为什么能够实现 Tree Shaking?
 7.2 发问 2:上面哪种状况会 Tree Shaking?

二 前言

返回目录

Tree ShakingWebpack 内置的一个优化,次要性能是移除 JavaScript 上下文中的未援用代码(dead-code)。

因为 JavaScript 大多数文件是要通过网络援用加载的,加载的文件越小,性能越好,所以 Tree Shaking 对于优化 JavaScript 很有意义。

你能够将援用程序设想成一棵树,而后外面有枯死的树叶和陈腐的树叶,你摇动它,枯死的树叶纷纷落下,你就看到一棵生机盎然的树。

三 什么是 dead-code

返回目录

  1. 代码不会被执行
  2. 代码执行后果不会被用到
  3. 代码只会影响死变量

即 JavaScript 上下文中的未援用代码(无用的,死的代码)。

举个例子:

project category

webpack-demo
 |- index.js
 |- main.js

main.js

export function square(x) {return x * x;}

export function cube(x) {return x * x * x;}

index.js

import {cube} from './main.js';

const result = cube(5);
const p = document.querySelector('.p');
p.innerHTML = result;

在这里,咱们并没有援用办法 square,所以整体来说 square 是未援用代码(dead-code),然而 Webpack 打包的时候会将 square 导出到 bundle 中。

四 什么是副作用?

返回目录

副作用是指:在导入时会执行非凡行为的代码,而不是仅仅裸露一个 export 或者多个 export

举个例子:polyfill 它影响全局作用域,并且通常不提供 export

五 如何做到 Tree Shaking

返回目录

在 Webpack 中,做到 Tree Shaking 的办法就是将一些文件表明为无副作用,这样就能够告知 Webpack 它能够平安地删除未用到的 export 导出。

package.json

{
  "name": "jsliang-project",
  "sideEffects": false
}

像下面,通过在 package.json 中定义 sideEffects 属性,就能够将文件标记为无副作用。

当然,如果有些文件你怕它有副作用,那就告知 Webpack 其中某些文件不须要标记:

package.json

{
  "name": "jsliang-project",
  "sideEffects": [
    "./src/math.js",
    "*.css*",
  ]
}

这里能够通过一个数组,数组反对 相干文件的相对路径、绝对路径和 glob 模式

这样,咱们就找出了 未应用代码 dead-code)。

然而正如下面所说,只是告知,并没有删除。

如果咱们须要在 bundle 中删除它们,就须要应用 -pproduction)这个 Webpack 编译标记,来启用 uglifyjs 压缩插件。

留神:--optimize-minimize 标记也会在 Webpack 外部调用 UglifyJSPlugin

webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  mode: "production"
};

六 总结

返回目录

为了达到 Tree Shaking 的作用,你须要:

  1. 应用 ES6 的模板语法 importexport
  2. 在我的项目 package.json 文件中,增加 sideEffects 入口。
  3. 引入一个可能删除未援用代码(dead-code)的压缩工具(例如 UglifyJSPlugin

七 其余问题

返回目录

7.1 发问 1:为什么能够实现 Tree Shaking?

返回目录

ES6 模块依赖关系是确定的,和运行时的状态无关,能够进行牢靠的动态剖析,这就是 Tree Shaking 的根底。

所谓的 动态剖析 ,就是不执行代码,从字面量上对代码进行剖析,ES6 之前的模块化,比方咱们能够动静 require 一个模块,只有执行后才晓得援用的什么模块,这个就不能通过动态剖析去做优化。

// demo.js
export const a = 'a';
export const b = 'b';

// test.js
import {a} from './demo.js';

// 以上代码不运行,仅仅通过扫描剖析,摈弃了 const b,代码缩减了 size
// 这就是 Tree Shaking 的动态剖析基本原理:有援用就保留,没有援用就摈弃 

所以为啥 CommonJS 不能 Tree Shaking 就是这个缘故。

7.2 发问 2:上面哪种状况会 Tree Shaking?

返回目录

// 全副导入
import _ from 'lodash';

// 具名导入
import {debounce} from 'lodash';

// 间接导入具体模块
import debounce from 'lodash/lib/debounce';

下面导入中:第一种的 全副导入 是不反对 Tree Shaking 的,其余都反对。

为什么呢?因为当你将整个库导入到单个 JavaScript 对象中时,就意味着你通知 Webpack,你须要整个库,这样 Webpack 就不会摇它。


jsliang 的文档库由 梁峻荣 采纳 常识共享 署名 - 非商业性应用 - 雷同形式共享 4.0 国内 许可协定 进行许可。<br/> 基于 https://github.com/LiangJunrong/document-library 上的作品创作。<br/> 本许可协定受权之外的应用权限能够从 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 处取得。

退出移动版