在上週末廣州舉辦的feday中,webpack的核心開發者Sean在介紹webpack插件系統原理時,隆重介紹了一箇中國學生於Google夏令營,在導師Tobias帶領下寫的一個webpack插件,webpack-deep-scope-analysis-plugin,這個插件可以大大提升webpack tree-shaking的效率。前端
tree-shaking 做爲 rollup 的一個殺手級特性,可以利用ES6的靜態引入規範,減小包的體積,避免沒必要要的代碼引入,webpack2也很快引入了這個特性,可是目前,webpack只能作比較簡單的解決方案,好比:webpack
import { isNumber, isNull } from 'lodash-es' export function fun1() { // do something } export function isNull(...args) { return isNull(...args) }
這個例子中,webpack會尋找引入變量的引用,當發現沒有對isNumber的引用時,就會去除isNumber的代碼。這其實不太實用,畢竟在如今的vscode中,沒有引用的變量在ide中都會灰顯提示,通常不會犯這種import某個模塊卻不用的錯誤了。git
若是是接下來這種引入方式呢,我寫了一個demo以下github
這個例子很是簡單,若是用圖來表示是這樣
web
在index.js中引入了func.js中的func2,並無引入func1,可是func1引入了lodash。webpack檢查的時候發現func.js中的確用到了lodash,因此不會把lodash去掉。實際上,咱們根本沒用到它。json
webpack-deep-scope-analysis-plugin就能夠解決這種判斷。babel
引入前
ide
引入後
函數
85.8kb -> 不到1kb 工具
固然,我這裏是標題黨了,由於這裏直接把一個lodash庫給去掉了,因此變化才這麼驚人。可是即便在實際項目中,咱們也能輕易用一個插件減小大量的沒必要要的引入。
原理方面,能夠參考做者的Medium文章,解釋得很是清楚,這裏不作贅述。
webpack的原理,其實就是遍歷全部的模塊,把它們打包成一個文件,在這個過程當中,它就知道哪些export的模塊有被使用到。那咱們一樣也能夠遍歷全部的scope(做用域),簡化沒有用到的scope,最後只留下咱們須要的。
咱們提到的這個webpack插件,正是內置了這樣一個scope分析器,它可以從入口文件中分析出scope的引用關係,最後排除掉全部沒有用到的模塊。
固然,這個插件也並非本身作了全部的事情,它也是依賴於了前人的工做。 escope 是一個分析ES中scope的工具,插件做者將它改爲了ts版本集成到了插件中,而且利用了webpack暴露的接口,能夠解析出來的模塊的AST樹,基於這個AST就能夠交給escope分析出scope的引用關係。
一些使用此插件的特殊狀況也能夠參考做者的原Medium文章。
首先,要用到tree-shaking,必然要保證引用的模塊都是ES6規範的。這也是爲何我在前面的demo中,引入的是lodash-es
而不是lodash
。
在項目中,注意要把babel
設置module: false
,避免babel將模塊轉爲CommonJS規範。引入的模塊包,也必須是符合ES6規範,而且在最新的webpack中加了一條限制,即在package.json
中定義sideEffect: false
,這也是爲了不出現import xxx
致使模塊內部的一些函數執行後影響全局環境,卻被去除掉的狀況。
當時跟這位插件做者溝通,他說未來有可能Tobias會把這個插件內置到webpack中,這也是符合webpack4零配置的趨勢。可是咱們也看獲得,要將前端工程的dead code elimination作到和其餘靜態語言同樣好,靠這些工具是遠遠不夠的,模塊自身也必須配合作到符合規範。
github項目地址:https://github.com/vincentdch...
Medium博客地址:https://medium.com/webpack/be...