参考链接

    production 模式下, Tree Shaking默认开启的。

    • tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)

      关联 - 函数副作用(函数式编程) 一个函数会、或者可能会对函数外部变量产生影响的行为

    • 它依赖于 ES2015 模块语法的 静态结构 特性,例如 importexport

    • 这个术语和概念实际上是由 ES2015 模块打包工具 rollup 普及起来的。

    使用场景
    Tree-shaking帮助我们删除掉没用到的代码。Tree-shaking这样的功能对于构建大型应用是非常好的,因为日常开发经常需要引用各种库。但大多数时候,仅仅使用了这些库的某些地方,并非需要全部,此时Tree-shaking如果能帮助我们删除掉没有使用的代码,将会大大缩减打包后的代码量。

    Tree-shaking的原理

    百度外卖前端:Tree-Shaking性能优化实践 - 原理篇

    总结:1.ES6的模块引入是静态分析的,故而可以在编译时正确判断到底加载了什么代码;2.分析程序流,判断哪些变量未被使用、引用、进而删除此代码。
    原理非常完美,那为什么我们的代码又删不掉呢? - 主要是副作用惹的锅。

    副作用
    了解过函数式编程的同学对副作用这词肯定不陌生。它大致可以理解成:一个函数会、或者可能会对函数外部变量产生影响的行为。
    举例说明

    1. function go (url) {
    2. window.location.href = url
    3. }

    这个函数修改了全局变量location,甚至还让浏览器发生了跳转,这就是一个有副作用的函数。

    现在我们了解了副作用了,但是细想来,我写的组件库也没有什么副作用啊,我每一个组件都是一个类,简化一下,如下所示:

    1. // componetns.js
    2. export class Person {
    3. constructor ({ name, age, sex }) {
    4. this.className = 'Person'
    5. this.name = name
    6. this.age = age
    7. this.sex = sex
    8. }
    9. getName () {
    10. return this.name
    11. }
    12. }
    13. export class Apple {
    14. constructor ({ model }) {
    15. this.className = 'Apple'
    16. this.model = model
    17. }
    18. getModel () {
    19. return this.model
    20. }
    21. }
    22. // main.js
    23. import { Apple } from './components'
    24. const appleModel = new Apple({
    25. model: 'IphoneX'
    26. }).getModel()
    27. console.log(appleModel)

    用rollup在线repl尝试了下tree-shaking,也确实删掉了Person,传送门
    可是为什么当我通过webpack打包组件库,再被他人引入时,却没办法消除未使用代码呢?
    因为我忽略了两件事情:babel编译 + webpack打包

    成也babel,败也babel
    Babel不用我多解释了,它能把ES6/ES7的代码转化成指定浏览器能支持的代码。正是由于它,我们前端开发者才能有今天这样美好的开发环境,能够不用考虑浏览器兼容性地、畅快淋漓地使用最新的JavaScript语言特性。
    然而也是由于它的编译,一些我们原本看似没有副作用的代码,便转化为了(可能)有副作用的。