近來廠里的項目越來越多,代碼共享必不可少。我現在采取的方案是:
- 把公共組件拿出來,開一個新倉庫
- 使用 webpack 進行打包編譯,
libraryTarget: 'umd'
- 將打包編譯的代碼一起提交到倉庫
- 使用
npm i <owner>/<repo> -S
安裝依賴,因為我廠的倉庫均為私有,所以不能發布到 NPM
這套方案簡單好用,實操效果良好。接下來我希望優化打包結果,於是研究了打包配置項,下面是我的一點心得。
@babel/preset-env
首先,Babel 推薦使用 @babel/preset-env 套件來處理轉譯需求。顧名思義,preset 即“預制套件”,包含了各種可能用到的轉譯工具。之前的以年份為准的 preset 已經廢棄了,現在統一用這個總包。
同時,babel 已經放棄開發 stage-* 包,以后的轉譯組件都只會放進 preset-env 包里。
browserslist
@babel/preset-env 支持一些參數,用來處理哪些 feature 要轉譯,哪些不要。其中比較重要的是 targets
,用來指定目標環境。targets
使用 browserslist 來篩選瀏環境,這樣我們就不需要指定所有瀏覽器版本,而可以使用類似 last 2 versions
這樣的描述。具體怎寫,可以看文檔,這里不再贅述。
如果你想知道自己配置的是否合適,可以在倉庫目錄下執行 npx browserslist
,列出所有目標瀏覽器,比如:
Babel 官方建議我們把 targets
寫到 .browserslistrc
或者 package.json
里,這樣其它工具也能更輕易的獲取到目標瀏覽器。另外,npx browserslist
無法從 .babelrc
等 babel 配置文件里讀取配置,所以執行的時候看到的會是默認結果。
useBuiltIns
接下來,我們可以配置 useBuiltIns
,這個屬性決定是否引入 polyfill。它有三個可選值,默認是 false
,即不引入,或者說,Babel 編譯結果不引入,把引入的位置、引入哪些 polyfill 交給用戶處理。因為我們的頁面中通常有大量的 JS,在每個文件里分別引用 polyfill 太浪費資源,所以可以在核心入口 JS 引用一次即可。
但是這樣我們必須手動 import '@babel/polyfill'
引入所有 polyfill,其實並不理想,因為大部分瀏覽器不需要這些。
所以推薦用 useBuiltIns: 'usage'
即“按需引用”。雖然文檔中標記為“experimental”,但我用起來也沒遇到什么問題。如果目標瀏覽器不支持需要的 feature,那么就引入 polyfill,不然的話就不引用。由於目前的打包工具越發智能,隨着 tree shaking 的完善,這樣可以最低限度引入 polyfill。
core-js
core-js 目前最新版本是 3.0.1,關於 v3 和 v2 的對比,大家可以看這篇博文:https://github.com/zloirock/core-js/blob/master/docs/2019-03-19-core-js-3-babel-and-a-look-into-the-future.md。這里簡單總結一下,core-js 2 封版於 1.5 年之前,所以里面只有對 1.5 年之前 feature 的 polyfill,最近 1.5 年新增的 feature 都不支持,也就存在因為新功能沒有 polyfill 於是在舊瀏覽器里失敗的風險。
所以我們應當升級到最新版,npm i core-js@3 -D
然后修改 babel 配置:
注意,目前 Vue Cli 3 集成了 core-js 2,不支持升級到 v3,無法手動升級。需要等待 Vue Cli 4。
@babel/polyfill
@babel/polyfill 是對 core-js 的封裝,引用了 core-js 的內容和生成器(regenerator-runtime)。 v7.4 之后,這個倉庫就被廢棄了,希望用戶自己選擇使用哪個兼容庫。
換言之,以前:
需要被替換成
不過我不建議這么做。對於絕大部分情況,使用 @babel/preset-env + useBuiltIns: 'usage'
仍然是最好的選擇。
總結
這些知識並不復雜,基本上文檔里都有。不過一次性看大量英文文檔可能對很多同學來說都是負擔。我比較提倡這樣學習:
- 遇到需求就去看一遍,不求全部理解,能解決目前的問題即可
- 重復這個過程,爭取每次都比上一次理解更多
- 建立不同工具之間的邏輯體系,要求能夠內恰
- 繼續重復這個過程,知道確認自己理解了
- 通過看文檔鞏固