npm run build 打包 之后怎么用_npm 组件你应该知道的事
開發(fā)一個 npm 組件, 你是否了解需要對外導出什么格式的代碼?如何讓 npm 組件體積盡可能小?
整篇文章按照如下目錄進行講解:
- 為何需要打包
- 組件打包輸出格式
- 如何打包 esm 模式代碼(感興趣選讀)
- 減少組件打包體積的最佳實踐
為何需要打包
首先,這里的打包概念解釋一下, 只要有輸出到新目錄,就稱為打包(免得大家對打包理解概念不一致)。
- 一份代碼,多種消費方式
- 使用新特性語法,由于一般項目中,會默認不對 node_module 中的庫進行編譯以提高整個項目的編譯速度,所以作為 npm 包,要轉換成 es5 ,免得消費方吐槽……
打包格式
按照目前主流的模塊系統(tǒng)來區(qū)分,可以先看一張圖片宏觀了解一下:
esm
如果是用 npm 組件來使用, 都推薦使用這種導出模式。
產生方式:
- rollup 聲明 target 為 esm 或者 babel 編譯之后生成一個新的目錄 (iceworks 的做法)
- package.json 中聲明 module,指向 esm
使用方式:
- 瀏覽器通過 引入
- 作為 npm 使用
特性
由于是靜態(tài)的,所以可以使用 tree-shaking
umd
使用方式
- 瀏覽器通過 引入
- 瀏覽器通過 requirejs 或 seajs ?引入 【目前這個已經很少使用了】
如何產生
- rollup 或者 webpack 聲明 target 為 umd
- package.json 中聲明 unpkg,指向對應文件
commonjs
使用方式
- node 端, npm 方式
如何產生
- rollup 或者 webpack 聲明 target 為 commonjs
- package.json 中聲明 main,指向對應文件 。
package.json 中引用優(yōu)先級如下:target 為 web 時, 依次查找 browser、module 和 main。其他 target , 依次找 module 和 main。因此如果聲明了 module, 會優(yōu)先讀取 module 中的路徑。
因此, 在導出的時候,同時設置好 main 和 module 字段,這樣就可以二者兼具了,在node端,瀏覽器端都可以正常使用。
webpack 如何打包 esm 模式
這里不講 rollup , 畢竟寫一個 target 就可以解決了。
大家都知道,webpack 的 target 沒有支持 esm 模式, 而 rollup 提供了, 為此很多人也在吐槽,為什么 webpack 不做……
我們這使用的是 iceworks , 源碼地址[1],它默認支持導出 esm 模式, 那就一起看看它的源碼是怎么做的。它是用 build-plugin-component 這個來實現(xiàn)的。【貼部分源碼,感興趣的可以看看】
- 如果不是 jsx 或 tsx 文件, 則直接 copy 到目標目錄,否則經過 bable 處理, 并將后綴改成 js
- 使用 babel-plugin-import 處理第三方依賴的組件庫,且兼容沒有 es 模塊的第三方組件
- 將 ts 解析生成 d.ts 文件
- bable 7 (@babel/preset-env ),若為 esm 模塊, 則關閉 module 選項
其實它實現(xiàn)的很簡單, 如果是 es 模塊, 只是用 babel 將對應的 es6 語法編譯成 es5 語法(且不選擇modlue), 然后 copy 到新目錄 es 下, 對于里面使用到的第三方依賴組件, 用 babel-plugin-import 做一下兼容處理。
組件打包體積的最佳實踐
首先,盡可能提供 esm 的格式, 因為它可以走 tree-shaking ,搖掉不必要的文件。【webpack 只要開啟 production 模式,就默認有 tree-shaking 功能】
tree-shaking
tree.png定義
如果被標記為無副作用的模塊沒有被直接導出使用,打包工具會跳過進行模塊的副作用分析評估。由此安全地刪除文件中未使用的部分。
在打包階段,webpack無法準確判斷某個文件是否有副作用,所以默認認為所有文件都是有副作用的。也就是說這里sideEffects默認是true。
副作用:一個函數(shù)會、或者可能會對函數(shù)外部變量產生影響的行為。
- 模塊作用域
將package.json 中sideEffects 設置為 false ,則表示改模塊全部忽略副作用
- 局部文件
package.json 中 sideEffects 數(shù)組寫對應文件,比如常見的寫上 css 文件, 如 antd 的配置
- 函數(shù)級別
/*@__PURE__*/ 聲明函數(shù)無副作用
只要我們基本保證這個組件包沒有對外部對象產生影響,就能設置 sideEffects: false 了
舉個栗子:設置了 sideEffects: false ?和 未設置 sideEffects: false ?的情況如下, 可以看到體積確實減少了不少
image.png更深入的 sideEffect 可以看看這篇文章[2]:
peerDependency
對于消費方可能也用到的組件,寫到 peerDependency 中。看下面一張圖就可以理解。這樣可以減少重復打包。
舉一個栗子:
"peerDependencies":?{????"react":?">=16.12.0",
????"react-dom":?">=16.12.0"
}
如上的配置,可以讓組件庫下的 node_modules 不安裝 react,同時指定組件庫使用方需安裝的 react/reactDOM 的版本。
external
對于打包成 umd 的文件,由于它無法分析是否存在 peerDependencies, 所以如果使用方已有 react、 react-dom 等庫,需要在webpack打包時,將 external 剔除掉對應依賴。
wepack5 模塊聯(lián)邦
external 還是靜態(tài)的,如果項目支持, 還可以使用 wepack5 Module Federation 方式,由使用方動態(tài)決定是否下載依賴。
總結
1. ?對外提供組件時,同時提供 esm ,commonjs, umd 這3種方式,并且在package 中對應的字段進行聲明,以確保這個包可以兼容多環(huán)境。
2. 盡可能提供 esm 模式,并且如果這個組件沒有影響外部變量時,設置 sideEffect 為 false, 讓使用方可以最大的 tree-shaking 。對于公用的依賴包,將其寫入 peerDependencies 中。
3. 若要提供 umd 模式, 在打包時, 將對應公用依賴寫入 external 剔除對應依賴。
參考資料
[1]源碼地址: https://github.com/ice-lab/iceworks
[2]文章: https://zhuanlan.zhihu.com/p/40052192
????歡迎留言討論????
推薦閱讀? ?前端學習計算機網絡——IP地址的劃分及其分類? ?前端學習計算機網絡——詳解DNS具體作用過程??【TCP/IP】圖解TCP的通信機制
???建議收藏 | 最全的JavaScript常見的操作數(shù)組的函數(shù)方法寶典
? ?多圖生動詳解瀏覽器與Node環(huán)境下的Event Loop
? ?HTML5新特性drag API 實現(xiàn)拖放功能
END
?支持三連
1.看到這里了就點個在看支持下吧,你的「在看」是我創(chuàng)作的動力。
2.關注公眾號前端印象,「一起交流進步」!
3.關注公眾號回復【加群】,拉你進技術交流群一起玩轉前端。
總結
以上是生活随笔為你收集整理的npm run build 打包 之后怎么用_npm 组件你应该知道的事的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python nan_python
- 下一篇: python源码文件_从源代码生成Pyt