前言
在上一篇npm init @vitejs/app的背後,僅是npm CLI的冰山一角[1]中,有提到我複習npm主要是從兩個大方向來入手,所以這篇繼續來講講package.json
這部分知識,經過這輪複習,也發現了自己的很多不足,之前把常用的命令和配置玩熟了,卻沒關心npm已經有了更多新的玩法,而這些玩法卻實實在在地在解決別人的問題。
npm 的配置還是挺多的,具體可以參考package.json官方文檔[2]。通讀了文檔之後,我略過了一些基礎的配置項,總結了一些我認爲比較有用的配置項。
常用配置項
files
files
定義了哪些文件應該被包括在 npm install 後的 node_modules中。
當然,有些文件是自動暴露出來的,不管你是不是配置了files
,比如:
-
package.json -
README / CHANGELOG / LICENSE -
...
很多庫都定義了 files,避免一些不必要的文件暴露到 node_modules 中。
vite 中是這樣配置的:
{
"files": [ "bin", "dist", "client.d.ts" ]
}
我之前就不知道這個配置,導致我發佈的一個 npm 組件 vue-awesome-progress[3] 就暴露了源碼部分,雖然這也沒啥影響,本來就是開源的。但是這也增加了別人的資源下載量,也是一種浪費。所以,專業點的搞法還是加上files
配置吧。
bin
bin 列出了可執行文件,表示你這個包要對外提供哪些腳本。
在這個包被 install 安裝時,如果是全局安裝 -g,bin 列出的可執行文件會被添加到 PATH 變量(全局可執行);如果是局部安裝,則會進入到 node_modules/.bin/ 目錄下。
bin 在一些 CLI 工具中用得很頻繁,比如 Vue CLI。
在開發 npm 包時,要求發佈的可執行腳本要以#!/usr/bin/env node
開頭,這是爲什麼呢?
我查了一下,原來是爲了用於指明該腳本文件要使用 node 來執行。
main, browser, module
這三個配置對我們的影響還是挺大的。
-
main
字段決定了別人require('xxx')
時,引用的是哪個模塊對象。在不設置main
字段時,默認值是index.js
。 -
如果你開發的包是用於瀏覽器端的,那麼用 browser
指定入口文件是最佳的選擇。 -
module
則代表你開發的包支持ESM
,並指定了一個ESM
入口。
具體這三個字段怎麼用,還是挺有學問的,這裏推薦一篇文章package.json中你還不清楚的browser,module,main 字段優先級[4],講得挺細。
長圖警告!
scripts
scripts
也基本上每天都用了,但是它的鉤子腳本你用過嗎?如果沒有用過,可以試試,在組織腳本流程時非常好用!
-
pre:在一個script執行前執行,比如prebuild,可以在打包前做一些準備工作。 -
post:在一個script執行後執行,比如postbuild,可以在打包後做一些收尾工作。
config
通過config
配置的參數xxx
,可以在腳本中通過npm_package_config_xxx
的形式引用,比如port
。
{
"config": {
"port": "8080"
}
}
依賴相關
dependencies
dependencies
可以理解爲生產依賴,通過npm install --save
安裝的依賴包都會進入到dependencies
中。
devDependencies
devDependencies
可以理解爲開發環境依賴,通常是一些工具類的包,比如 webpack, babel等。通過npm install --save-dev
安裝的依賴包都會進入到devDependencies
中。
但是,在結合一些構建工具使用時,我們往往會有困惑。比如我安裝了一個包到devDependencies
中,但是不小心在項目中引用了它,最後也被 webpack 打包到構建結果中了。這是怎麼回事呢?
建議結合上篇文章npm install這一節[5]一起看。
peerDependencies
我是package-a,你裝我,你就必須裝我的peerDependencies。
讓“調包俠”將package-a的依賴提升到自己的node_modules
中,這樣可以在“調包俠”和package-a都需要同一個依賴(比如vue)時,避免重複安裝。這常見於開發組件或者庫。
注意,一個 npm 包的開發者如果聲明瞭peerDependencies
,開發環境下在該包目錄npm install
也不會在node_modules
中安裝這些依賴,所以往往還需要藉助devDependencies
。
舉個例子,我開發一個組件,不想發佈到 npm 時包含了 vue 的代碼,這就需要外部提供 vue ,所以我把 vue 定義在 peerDependencies 也無可厚非。但是,在開發組件時,一般還需要本地開發環境跑一個 demo 試試效果,這時候是依賴 vue 的,所以還需要在 devDependencies 中安裝 vue 。我看了下 vue-router 就是這麼做的,所以我在開發自己的組件時也學會了這招。
bundledDependencies
bundledDependencies
跟上面的依賴都不太一樣,配置上不是鍵值對的形式,而是一個數組。
{
"bundledDependencies": [
"vue",
"vue-router"
]
}
在運行npm pack
時,會將對應依賴打包到tgz
文件中。用得不多,不知道具體的細節,主要還是直接用npm install
安裝 tgz 包的場景比較少,有個概念就行。
optionalDependencies
optionalDependencies
用於配置可選的依賴,即使配了這個,代碼裏也要做好判斷(保護),否則運行報錯就不好玩了。
try {
var foo = require('foo')
var fooVersion = require('foo/package.json').version
} catch (er) {
foo = null
}
題外話
仔細讀過package.json
文檔後,整體上還是解決了我的不少困惑,對我開發 npm 組件也提供了不少幫助。如果您想了解更多細節和實戰,不妨打開我這個項目vue-awesome-progress[3]看看,希望對您有所幫助!
參考
npm init @vitejs/app的背後,僅是npm CLI的冰山一角: https://juejin.cn/post/6950817077670182943
[2]package.json官方文檔: https://docs.npmjs.com/cli/v7/configuring-npm/package-json
[3]vue-awesome-progress: https://cumt-robin.github.io/vue-awesome-progress/
[4]package.json中你還不清楚的browser,module,main 字段優先級: https://www.cnblogs.com/qianxiaox/p/14041717.html
[5]上篇文章npm install這一節: https://juejin.cn/post/6950817077670182943#heading-6
回覆“加羣”與大佬們一起交流學習~
點擊“閱讀原文”查看 120+ 篇原創文章
本文分享自微信公衆號 - 前端自習課(FE-study)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。