所以我们现在理解了,当时babel编译成的 _createClass方法为什么会有副作用。现在再回头一看,它简直浑身上下都是副作用。
查看uglify的具体配置,我们可以知道,目前uglify可以配置 pure_getters: true来强制认为获取对象属性,是没有副作用的。这样可以通过它删除上述示例中的 square方法。不过由于没有 pure_setters这样的配置, _createClass方法依旧被认为是有副作用的,无法删除。
聪明的同学肯定会想,既然babel编译导致我们产生了副作用代码,那我们先进行tree-shaking打包,最后再编译bundle文件不就好了嘛。这确实是一个方案,然而可惜的是:这在处理项目自身资源代码时是可行的,处理外部依赖npm包就不行了。因为人家为了让工具包具有通用性、兼容性,大多是经过babel编译的。而最占容量的地方往往就是这些外部依赖包。
那先从根源上讨论,假如我们现在要开发一个组件库提供给别人用,该怎么做?

先贴下webpack将项目打包为JS库的 文档。可以看到webpack有多种导出模式,一般大家都会选择最具通用性的 umd方式,但是webpack却没支持导出ES模块的模式。
所以,假如你把所有的资源文件通过webpack打包到一个bundle文件里的话,那这个库文件从此与Tree-shaking无缘。
那怎么办呢?也不是没有办法。目前业界流行的组件库多是将每一个组件或者功能函数,都打包成单独的文件或目录。然后可以像如下的方式引入:
import clone from 'lodash/clone' import Button from 'antd/lib/button';
但是这样呢也比较麻烦,而且不能同时引入多个组件。所以这些比较流行的组件库大哥如antd,element专门开发了babel插件,使得用户能以 import { Button, Message } form 'antd'这样的方式去按需加载。本质上就是通过插件将上一句的代码又转化成如下:
import Button from 'antd/lib/button'; import Message from 'antd/lib/button';
这样似乎是最完美的变相tree-shaking方案。唯一不足的是,对于组件库开发者来说,需要专门开发一个babel插件;对于使用者来说,需要引入一个babel插件,稍微略增加了开发成本与使用成本。
除此之外,其实还有一个比较前沿的方法。是rollup的一个 提案,在package.json中增加一个key:module,如下所示:
{
"name": "my-package",
"main": "dist/my-package.umd.js",
"module": "dist/my-package.esm.js"
}
这样,当开发者以es6模块的方式去加载npm包时,会以 module的值为入口文件,这样就能够同时兼容多种引入方式,(rollup以及webpack2+都已支持)。但是webpack不支持导出为es6模块,所以webpack还是要拜拜。我们得上rollup!
(有人会好奇,那干脆把未打包前的资源入口文件暴露到 module,让使用者自己去编译打包好了,那它就能用未编译版的npm包进行tree-shaking了。这样确实也不是不可以。但是,很多工程化项目的babel编译配置,为了提高编译速度,其实是会忽略掉 node_modules内的文件的。所以为了保证这些同学的使用,我们还是应该要暴露出一份编译过的ES6 Module。)
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-59797-5.html
很棒
我们这些老家伙积累点钱防老
多去贴吧了解下真实实力不懂不要紧
还有的多了