chst365's blog chst365's blog
首页
  • Git
  • 网络
  • 操作系统
  • 浏览器
  • webpack
  • JavaScript
  • TypeScript
  • 性能
  • 工程化
  • React
  • 编程题
  • React技术揭秘
  • 算法
  • Node
  • 编码解码
  • NodeJS系列
  • Linux系列
  • JavaScript系列
  • HTTP系列
  • GIT系列
  • ES6系列
  • 设计模式系列
  • CSS系列
  • 小程序系列
  • 数据结构与算法系列
  • React系列
  • Vue3系列
  • Vue系列
  • TypeScript系列
  • Webpack系列
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

chst365

DIV工程师
首页
  • Git
  • 网络
  • 操作系统
  • 浏览器
  • webpack
  • JavaScript
  • TypeScript
  • 性能
  • 工程化
  • React
  • 编程题
  • React技术揭秘
  • 算法
  • Node
  • 编码解码
  • NodeJS系列
  • Linux系列
  • JavaScript系列
  • HTTP系列
  • GIT系列
  • ES6系列
  • 设计模式系列
  • CSS系列
  • 小程序系列
  • 数据结构与算法系列
  • React系列
  • Vue3系列
  • Vue系列
  • TypeScript系列
  • Webpack系列
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 浏览器

  • webpack

  • TypeScript

  • 性能

  • 工程化

    • webpack-loader机制
    • webpack-插件机制
    • webpack工作流程
    • Babel原理
    • uglify-js代码是如何被压缩的
    • Tree-Shaking性能优化
      • 什么是 Tree-shaking
      • DCE
      • tree-shaking 原理
        • ES6 module 特点
        • 总结
    • 前端模块化机制
    • 前端微服务
    • Vite为什么快?快在哪?
    • npm script了解多少?
  • React

  • JavaScript

  • 编程题

  • React技术揭秘

  • 算法

  • 前端
  • 工程化
chst365
2021-04-16
目录

Tree-Shaking性能优化

# 什么是 Tree-shaking

上图形象解释了 Tree-shaking 的本意。在 webpack 项目中,有一个入口文件,相当于一颗树的主干,入口文件有很多依赖的模块,相当于树枝。实际情况中,虽然依赖了某个模块,但其实只使用其中的某些功能。通过 tree-shaking,将没用的模块摇调,这样达到删除无用代码的目的。

现支持 tree shaking 的工具有 Rollup (opens new window)、Webpack (opens new window)、closure-compiler (opens new window).

DCE(dead code elimination): 编译器可判断出某些代码不影响输出,然后消除这些代码。 Tree-shaking 是 DCE 的一种新的实现,传统的 DCE 消灭不可能执行的代码,而 Tree-shaking 消除没有用到的代码。

# DCE

  • 代码不会被执行,不可到达
  • 代码执行的结果不会被用到
  • 代码只会影响死变量(只写不读)

js 的 DCE 由 uglify 完成

中间为 rollup 打包的结果,右边是 webpack 打包的结果 rollup 将无用的代码 foo/unused 函数消除了,但仍保留不会执行到的代码,而 webpack 则完整保留了无用代码和不会执行的代码

分别用 rollup + uglify 和 webpack + uglify 将代码进行打包 中间为配置文件,右侧是结果,可看出结果中都去除了无法执行的代码

# tree-shaking 原理

# ES6 module 特点

  • 只能作为模块顶层的语句出现
  • import 的模块名只能是字符串常量
  • import binding 是 immutable 的

ES6 模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,这是 tree-shaking 的基础。 所谓静态分析就是不执行代码,从字面量上对代码进行分析,ES6 之前的模块化,动态 require 一个模块,只有执行后才知道引用什么模块,不能通过静态分析做优化。

面向过程编程和面向对象编程,从这两个方面来实验

  • 函数消除实验 utils 中 get 方法没有被使用到,我们期望 get 方法最终被消除 注意:uglify 目前不支持跨文件做 DCE,所以上面这种情况,uglify 是不能优化的

    上图 rollup 打包结果,符合预期

    上图 webpack 打包结果,也符合预期,但是没有 rollup 更优化

  • 类消除实验

    ![](https://user-gold-cdn.xitu.io/2018/1/4/160bfd6bd77e84e0?imageView2/0/w/1280/h/960/format/webp/ignore-error/1 由图看出,main.js引用了menu.js,但没有用到 menu 的任何方法和变量,期望最终代码消除menu.js的内容

    rollup 打包后,还包含了menu.js的全部代码

    webpack 打包后,也包含了menu.js的全部代码

    看来,webpack 和 rollup 对类消除不太友好,那么 closure-compiler 呢?

    closure compiler, tree-shaking 的结果完美!

    但能得到这么完美结果是有条件的,那就是 cc 的侵入式约束规范,需添加如下图代码

    google 定义一整套注解规范 Annotating JavaScript for the Closure Compiler,想更多了解的,可以去看下官网。侵入式这个就让人很不爽,google Closure Compiler 是 java 写的,和我们基于 node 的各种构建库不可能兼容(不过目前好像已经有 nodejs 版 Closure Compiler),Closure Compiler 使用起来也比较麻烦,所以虽然效果很赞,但比较难以应用到项目中,迁移成本较大。

# 总结

三大工具的 tree-shaking 对于无用代码,无用模块的消除,都是有限的,有条件的。closure compiler 是最好的,但与我们日常的基于 node 的开发流很难兼容。 tree-shaking 对 web 意义重大,是一个极致优化的理想世界,是前端进化的又一个终极理想。

#前端#工程化
上次更新: 2021/12/14, 23:27:23
uglify-js代码是如何被压缩的
前端模块化机制

← uglify-js代码是如何被压缩的 前端模块化机制→

最近更新
01
面试官
03-27
02
this&指针&作用域&闭包
03-27
03
前端
03-27
更多文章>
Theme by Vdoing | Copyright © 2019-2025 chst365 | 豫ICP备17031889号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式