這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 工程化最開始就是package.json開始的,很多人學了很多年也沒搞清楚這個為什麼這麼神奇,其實有些欄位是在特定場景才有效的,那每個屬性的適用場景和作用是什麼,又牽扯很多知識點,今天先解讀一些常見的屬性,關註我,後期在遇到特定場景也會再 ...
這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助
工程化最開始就是package.json開始的,很多人學了很多年也沒搞清楚這個為什麼這麼神奇,其實有些欄位是在特定場景才有效的,那每個屬性的適用場景和作用是什麼,又牽扯很多知識點,今天先解讀一些常見的屬性,關註我,後期在遇到特定場景也會再逐步的補充這些屬性,只有真正清楚知道每個自動的屬性和場景你才能真正使用它得心應手,也才能真正掌握並幫助你解決你的問題。
創建
一個package.json 你可以使用npm init
按指令創建,也可以通過npm init -y
來快速創建,當然也可以手動來創建,那現在我們創建一個。 package.json
{ "name": "package-demo", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC" }
這個是原裝的屬性,當然還有一些額外的場景才有的,接下來我們來逐步分析:
常用屬性
這些屬性沒有沒有太複雜,但還是要仔細看看每個都可以做什麼,適用於什麼場景,如何去使用和配置
name
package.json 中最重要欄位之一就是名稱name 欄位,有人的說為什麼我沒有配置也沒有影響我項目的正常運行呢?這個是因為你沒有發佈npm 包,這個name就是你發佈到npm的包名,如果你不打算發佈你的包到npm上這個是可以省略的。
當然這個名稱也不是隨便亂起的,它也有一定的規則,否則有警告的如下:
字元串與 "^(?:(?:@(?:[a-z0-9-*~][a-z0-9-*._~]*)?/[a-z0-9-._~])|[a-z0-9-~])[a-z0-9-._~]*$" 的模式不匹配。
name的規則如下:
- 名稱必須少於或等於 214 個字元。 這包括範圍包的範圍。
- 範圍包的名稱可以以點或下劃線開頭。 沒有範圍是不允許的。
- 新包的名稱中不得包含大寫字母。
- 該名稱最終成為 URL、命令行參數和文件夾名稱的一部分。 因此,名稱不能包含任何非 URL 安全字元
version
這個是版本,跟name
欄位差不多,基本是一起的,因為它們共同構成一個假定完全唯一的標識符,如果你不發佈包也是這個省略這個欄位的,當然這個欄位值也不是隨意寫的,它完全基於符合語義化版本(Semantic Versioning)來管理依賴的版本,所以版本號的更新需要符合語義化版本規範,簡單總結:可以被 semver
包可解析的,當然你也可以使用這個semver
進行版本的操作,具體可以看我的另一篇版本號文章版本號
keywords
這個也是發佈到npm 上才有用的,它的作用也是別人可以通過搜索來查找你的包,或是通過npm search xxx
開查找你的包 如下,我有兩個運行時的包處理react preact 的className的,可以看看查出了什麼:
PS D:\lucky-file\package-demo> npm search 'react runtime clsx' NAME | DESCRIPTION | AUTHOR | DATE | VERSION | KEYWORDS react-auto-clsx | | =crazy-code | 2023-10-10 | 1.1.0 | react vite webpack className clsx runtime react-runtime-clsx | | =zsh-yzy | 2023-11-30 | 0.0.1 | react vite webpack className clsx runtime react-auto-classnames | JSX runtime for… | =meowtec | 2022-09-30 | 1.0.2 | react classnames clsx jsx-runtime PS D:\lucky-file\package-demo>
是不是幾個包的信息,所以這個是搜索查找用的,如果你不發佈這個也可以不寫的
homepage
項目主頁的 url。隨便找個npm 包,可以看一下,該包的右側有個地址就是這個欄位進行配置的
bugs
這個就是要需要作者給個地址,比如你寫的包有問題,別人怎麼給你提問題,聯繫到你 通常我們設置的issue地址,那如何打開呢,可以通過如下方式:
npm bugs [<pkgname> [<pkgname> ...]]
license
指定一個許可證,以便人們知道他們如何被允許使用它,以及你對其施加的任何限制,常見的開源協議是 MIT 和 BSD,如果我們不確定我們應該如何寫,可以看一下網上這個圖說的比較清晰借用一下:
author
它表示項目的作者信息,它既可以是一個字元串,又可以是一個對象
"author":{ "name": "lvz", "email": "[email protected]", "url": "https://xxxxx" }
或者使用字元串的形式也可以
"author": "lvz <[email protected]> (https://xxxxx)"
contributors
contributors 它表示的是貢獻者,是一個數組,當然這個也有兩種寫法
"contributors": [ "lvz1 <[email protected]> (https://xxxxx)" ]
或者對象的寫法
"contributors":[ { "name": "lvz1", "email": "[email protected]", "url": "https://xxxxx" } ]
funding
如果你不開源,對資金沒有要求或有其它渠道可以不使用,這個是在npm 6.13.0添加了funding
命令,針對開源者,讓維護 npm 的開發人員,為有意願的捐贈者指明捐贈平臺。在 package.json 文件中添加了一個funding
欄位,指向線上捐贈服務的 url,如 Patreon、Open 或者其他支付網站,並可以通過npm fund
命令列出這些捐贈平臺及其 url。
"funding": [ { "type": "patreon", "url": "http://XXXXXX" }, "http://XXXXX", { "type": "open", "url": "https://XXXXXX" } ]
files
項目在進行 npm 發佈時,可以通過 files 指定需要跟隨一起發佈的內容來控制 npm 包的大小,避免安裝時間太長,比如我們包體有很多文件,但我們只想把dist放進去,其他src,test文件並不想放在包體中,可以使用這個欄位
但無論設置如何,總是會包含某些文件:
package.json
README
CHANGES
/CHANGELOG
/HISTORY
LICENSE
/LICENCE
NOTICE
- “main”欄位中的文件 相反,某些文件總是被忽略:
.git
CVS
.svn
.hg
.lock-wscript
.wafpickle-N
.*.swp
.DS_Store
._*
npm-debug.log
.npmrc
node_modules
config.gypi
*.orig
package-lock.json
當然除了files 也有其它方式可以來忽略文件進入包體,我們先看一下我們什麼也不處理的文件格式
- 添加.gitignore文件
src/* example/*
我們發佈之後在看一下文件結構,只有index.js 也就是main欄位指向的index.js還有package.json兩個文件
- 添加.npmignore 文件
src/* example
同樣我們發佈之後看一下文件結構,如下圖所示:
.npmignore在程式包的根目錄下,它不會覆蓋“files”欄位,但在子目錄中,它將覆蓋。該
.npmignore
文件的工作方式與一樣.gitignore
。如果有.gitignore
文件但.npmignore
缺少文件,.gitignore
則將使用的內容
repository
簡單點說就是配置倉庫地址,這個配置後,可以在npm 包首頁看到倉庫地址入口,可以進行點擊查看
"repository": { "type": "git", "url": "https://github.com/xxxxx", "directory": "xxxx/xxx" }
當然你也可以直接寫字元串
"repository":"https://github.com/xxxxx/xxxx"
config
配置對象可用於設置在升級後持續存在的包腳本中使用的配置參數
"config": { "type": "chrome" },
我們在index.js中進行列印一下
console.log(process.env.npm_package_config_type)
此時如果你直接node index.js 你會發現列印的是個undefined,我們在將其放在scripts中:
"scripts": { "start": "node index.js" },
再執行就可以列印出值了,這樣我們就可以在腳本中使用了這個環境變數了。
依賴配置項
這個是我們這次的重點之一,其實有些朋友經常分不清,這些到底怎麼回事,我們先整體分析一下,我們安裝一個包有兩種,一種是當前項目package.json 已有的,一種是安裝包中package.json的依賴,那針對這個我們做個實驗再總結一下看看它們都是什麼妖魔鬼怪。
我們在介紹version這個欄位的時候,講解瞭如何安裝一個指定範圍的npm包,如果有疑問可以進去查看哈,這裡就不再贅述了
背景 有兩個項目,一個是project-demo,一個是package-demo,包名是lucky-package-demo
,project-demo會依賴lucky-package-demo
這個包。 如下project-demo 中的package.json
"dependencies": { "lucky-package-demo": "*" }
devDependencies
簡單理解就是這個包是開發環境用到了,生產環境並不需要它,比如我們的webpack,vite,或是eslint等
我們在package-demo 中安裝 vite
"devDependencies": { "vite": "4.3.0" }
然後我們在project-demo更新lucky-package-demo
後,可以看到project-demo的node_modules中發現react 和 react-demo 已經被安裝了,雖然暫時我們並沒有去使用這兩個包,也就是說dependencies中的包將會被安裝
peerDependencies
也叫同等依賴,它主要用於確保多個模塊在同一個主模塊的上下文中使用,並共用依賴的版本,簡單來說就是project-demo項目中已經安裝react了,package-demo中我沒必要在dependencies依賴這個react了。從而避免項目中和依賴包中出現重覆安裝包所導致的包版本不相容、打包了多份不同版本的庫等問題,我們舉幾個常遇到的問題來解釋一下這個屬性。
- 我有一個組件庫,依賴了react,項目中我也要使用react並且已經安裝好了,組件庫和項目可以共用react
- 但有個問題,我項目更新了,react的版本和組件庫react的版本不一致了,還是共用,如何避免衝突
安裝方式:
我們可以配合一些屬性使用,在依賴包中,因為我們不會在項目包中安裝,可以放在devDependencies中,我們又想告訴項目包我們需要什麼範圍內的版本,就需要設置peerDependencies,如下:
package-demo中如下配置
"devDependencies": { "react": "17.0.2", "vite": "4.3.0" }, "peerDependencies": { "react":">16.8.0 <18.0.0" }如果我們在project-demo中安裝的是
react:"17.0.1"
,此時是滿足我們依賴包中peerDependencies中對react的版本範圍要求的,安裝很順利,項目和依賴包會共用17.0.1的react的包,也不會存在任何警告。dependencies: - lucky-package-demo + lucky-package-demo 0.0.10 - react + react 17.0.1 (18.2.0 is available)但如果此時我們將project-demo中react緩存16.8.0此時會有如下提示,因為此時16.8.0 是不滿足peerDependencies中react版本範圍要求的,此時你手動處理一下,要麼安裝正確的版本,要麼通知作者更新一下peerDependencies
dependencies: - lucky-package-demo + lucky-package-demo 0.0.10 - react + react 16.8.0 (18.2.0 is available) WARN Issues with peer dependencies found . └─┬ lucky-package-demo 0.0.10 └── ✕ unmet peer react@">16.8.0 <18.0.0": found 16.8.0
peerDependenciesMeta
如果 peerDependencies
中指定的包尚未安裝,npm 將發出警告,如下配置將對等依賴標記為可選,如果用戶沒有安裝對等依賴,npm不會發出警告
"peerDependenciesMeta":{ "react":{ "optional":true } }在project-demo中安裝
lucky-package-demo
,可以發現node_modules中並不存在react的包,控制台也沒有任何的警告出現npm i -S lucky-package-demo
如果設置成optional:false
中,在project-demo中安裝lucky-package-demo
後將會自動安裝符合範圍的react的包
bundleDependencies
npm的命令 -B, --save-bundle
語法:npm i -B [package-name]
這個屬性使用的較少,通過在 bundleDependencies
數組中指定包名稱,在發佈包時,包名的數組會被打包進去,有的說我試過但發佈包什麼也沒有呢?因為單單配置bundleDependencies
這個是沒有效果的,需要再在依賴包中安裝devDependencies或dependencies中才能將其打包到node_modules中。舉例說明:
在package-demo 中進行如下安裝和配置,併在project-demo中npm i -S lucky-package-demo
安裝,你會發現project-demo中的node_modules中lucky-package-demo的node_modules中是bundleDependencies中配置的react-runtime-clsx包
"dependencies": { "react-runtime-clsx": "0.0.1" }, "bundleDependencies": [ "react-runtime-clsx" ]當然你可以在package-demo跟目錄執行npm pack,和安裝lucky-package-demo一樣,可以看看目錄結構:
project-demo ----node_modules -------lucky-package-demo -----------node_modules ---------------react-runtime-clsx //這個是bundleDependencies配置的 ---------------clsx 這個是react-runtime-clsx的依賴
optionalDependencies
通過npm 命令 -O, --save-optional
npm i -O [package-name]
optionalDependencies
用於定義可選依賴項,和 dependencies
非常類似,主要的差別在於:在 optionalDependencies
中的依賴包安裝報錯甚至找不到時不會影響到包管理器的安裝行為
npm i -O react-runtime-clsx // package-demo package.json 如下: "optionalDependencies": { "react-runtime-clsx": "0.0.1" }
optionalDependencies
中的條目將覆蓋dependencies
中的同名條目,因此通常最好只放在一個位置
overrides
如果需要對依賴項的依賴項進行特定更改,例如將依賴項的版本替換為已知的安全問題,將現有依賴項替換為分支,或者確保在任何地方都使用相同版本的包,則可以添加覆蓋。
package-demo中package.json 配置
"optionalDependencies": { "react-runtime-clsx": "0.0.1" }
具體的大家可以看一下文檔overrides文檔 )
項目中的依賴
項目中我們也會有依賴,有些是輔助開發的工具,有些是項目引用的代碼包,因為項目我們是不會發佈它作為npm包來使用的,它作為的是一個工程,所以在依賴上是有區分的,你是不是也有下麵的困惑呢?
我隨便裝的並不影響到開發和構建,似乎這兩者沒有區別,安裝哪裡都一樣呢?
感覺是對的,其實項目中這兩者並沒有明顯的劃分,只是我們通常是將開發中使用的安裝到devDependencies,運行使用的放在dependencies,其實這兩個都是安裝了的,無論你放哪都可以使用,所以也有部分剛接觸時很困惑,因為這個針對的是npm發佈包有用的,在項目中還是按規範了養成習慣,清楚每個的含義,對我們做npm包的發佈是有用的哈