国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

現(xiàn)代 JavaScript 庫(kù)打包指南

開(kāi)發(fā)
大家好今天給大家分享一篇JavaScript庫(kù)打包的參考指南,如果你也在維護(hù)一些JavaScript庫(kù),可以參考一下。

本指南旨在提供一些大多數(shù)庫(kù)都應(yīng)該遵循的一目了然的建議。以及一些額外的信息,用來(lái)幫助你了解這些建議被提出的原因,或幫助你判斷是否不需要遵循某些建議。這個(gè)指南僅適用于 「庫(kù)(libraries)」,不適用于應(yīng)用(app)。

要強(qiáng)調(diào)的是,這只是一些「建議」,并不是所有庫(kù)都必須要遵循的。每個(gè)庫(kù)都是獨(dú)特的,它們可能有充足的理由不采用本文中的任何建議。

最后,這個(gè)指南不針對(duì)某一個(gè)特定的打包工具 —— 已經(jīng)有許多指南來(lái)說(shuō)明如何在配置特定的打包工具。相反我們聚焦于每個(gè)庫(kù)和打包工具(或不用打包工具)都適用的事項(xiàng)。

輸出 esm、cjs? 和 umd 格式

  • esm 是“EcmaScript module”的縮寫(xiě)。
  • cjs 是“CommonJS module”的縮寫(xiě)。
  • umd? 是“Universal Module Definition”的縮寫(xiě),它可以在 <script>? 標(biāo)簽中執(zhí)行、被 CommonJS? 模塊加載器加載、被 AMD 模塊加載器加載。

esm? 被認(rèn)為是“未來(lái)”,但 cjs? 仍然在社區(qū)和生態(tài)系統(tǒng)中占有重要地位。esm? 對(duì)打包工具來(lái)說(shuō)更容易正確地進(jìn)行 treeshaking,因此對(duì)于庫(kù)來(lái)說(shuō),擁有這種格式很重要?;蛟S在將來(lái)的某一天,你的庫(kù)只需要輸出 esm。

你可能已經(jīng)注意到,umd? 已經(jīng)與 CommonJS 模塊加載器兼容 —— 所以為什么還要同時(shí)具備 cjs? 和 umd? 輸出呢?一個(gè)原因是,與 umd 文件相比,CommonJS 文件在對(duì)依賴進(jìn)行條件導(dǎo)入時(shí)通常表現(xiàn)更好;例如:

if (process.env.NODE_ENV === "production") {
module.exports = require("my-lib.production.js");
} else {
module.exports = require("my-lib.development.js");
}

上面的例子,當(dāng)使用 CommonJS 模塊時(shí),只會(huì)引入 production? 或 development 包中的一個(gè)。但是,對(duì)于 UMD 模塊,最終可能會(huì)將兩個(gè)包全部引入。有關(guān)更多信息,請(qǐng)參閱此討論。

最后還需要注意是,開(kāi)發(fā)者可能會(huì)在其應(yīng)用中同時(shí)使用 cjs? 和 esm?,發(fā)生雙包危險(xiǎn)。dual package hazard 一文介紹了一些緩解該問(wèn)題的方法,利用 package.json#exports 進(jìn)行 package exports 也可以幫助防止這種情況的發(fā)生。

輸出多文件

通過(guò)保留文件結(jié)構(gòu)更好地支持 treeshaking。

如果你對(duì)你的庫(kù)使用了打包工具或編譯器,可以對(duì)其進(jìn)行配置以保留源文件目錄結(jié)構(gòu)。這樣可以更容易地對(duì)特定文件進(jìn)行 side effects 標(biāo)記,有助于開(kāi)發(fā)者的打包工具進(jìn)行 threeshaking。

一個(gè)例外是,如果你要?jiǎng)?chuàng)建一個(gè)不依賴任何打包工具可以直接在瀏覽器中使用的產(chǎn)出(通常是 umd? 格式,但也可能是現(xiàn)代的 esm 格式)。在這種情況下,最好讓瀏覽器請(qǐng)求一個(gè)大文件,而不是請(qǐng)求多個(gè)小文件。此外,你應(yīng)該進(jìn)行代碼壓縮并為其創(chuàng)建 sourcemap。

要不要壓縮代碼

你可以將一些層面的代碼壓縮應(yīng)用到你的庫(kù)中,這取決于你對(duì)你的代碼最終通過(guò)開(kāi)發(fā)者的打包工具后的大小的追求程度。

例如,大多數(shù)編譯器已經(jīng)配置了刪除空白符等其他簡(jiǎn)單的優(yōu)化,即使是來(lái)自 NPM 模塊的代碼(在這里指的是你的庫(kù))。使用 terser —— 一個(gè)流行的 JavaScript 代碼壓縮工具 —— 這類壓縮工具可以將包的最終大小減少 95%。在某些情況下,你可能會(huì)對(duì)這些優(yōu)化感到滿意,且不需要你來(lái)付出任何努力。

但如果在發(fā)布前對(duì)你的庫(kù)進(jìn)行代碼壓縮,這可以得到一些額外的好處,但需要深入了解壓縮工具的配置和副作用。壓縮工具通常不會(huì)將這類壓縮用于 NPM 模塊,因此,如果你不自己來(lái)做的話,你會(huì)錯(cuò)過(guò)這些節(jié)省。

最后,如果你正創(chuàng)建一個(gè)不依賴任何打包工具可以直接在瀏覽器中使用的產(chǎn)出(通常是 umd? 格式,但也可以是現(xiàn)代的 esm 格式)。在這種情況下,你應(yīng)該對(duì)代碼進(jìn)行壓縮,并創(chuàng)建 sourcemap,并輸出到一個(gè)單文件。

創(chuàng)建 sourcemap

對(duì)源代碼進(jìn)行任何形式的編譯,都將導(dǎo)致未來(lái)某個(gè)異常的位置,無(wú)法與源碼對(duì)應(yīng)起來(lái)。為了幫助未來(lái)的自己,創(chuàng)建 sourcemap,即使只進(jìn)行了很少的編譯工作。

創(chuàng)建 TypeScript 類型

隨著使用 TypeScript 的開(kāi)發(fā)者數(shù)量不斷增長(zhǎng),將類型內(nèi)置到你的庫(kù)中將有助于改善開(kāi)發(fā)體驗(yàn) (DX)。此外,不使用 TypeScript 的開(kāi)發(fā)者在使用支持類型的編輯器(例如 VSCode,它使用類型來(lái)支持其 Intellisense 功能)時(shí)也會(huì)獲得更好的 DX。

但是,創(chuàng)建類型并不意味著你必須使用 TypeScript 來(lái)編寫(xiě)你的庫(kù)。

一種選擇是繼續(xù)在源代碼中使用 JavaScript,然后通過(guò) JSDoc 注釋來(lái)支持類型。然后,你可以將 TypeScript 配置為僅從你的 JavaScript 源代碼中構(gòu)建類型文件。

另一種選擇是直接在 index.d.ts 文件中編寫(xiě) TypeScript 類型文件。

獲得類型文件后,請(qǐng)確保設(shè)置了 package.json#exports? 和 package.json#types 字段。

外置框架

不要將 React、Vue 等框架打包在你的庫(kù)中。

當(dāng)構(gòu)建的庫(kù)依賴某個(gè)框架(例如 React、Vue 等),或是作為另一個(gè)庫(kù)的插件,你可能需要將框架配置到“externals”中。這可以使你的庫(kù)引用這個(gè)框架,但不會(huì)將其打包到最終的產(chǎn)出中。這會(huì)避免產(chǎn)生一些 bug,并減少庫(kù)的體積。

你應(yīng)該還需要將框架添加到庫(kù)的 package.json 的 peer dependencies 中,這將幫助開(kāi)發(fā)者發(fā)現(xiàn)你依賴于某個(gè)框架。

面向現(xiàn)代瀏覽器

使用現(xiàn)代的新特性,如果有需要,讓開(kāi)發(fā)者支持舊的瀏覽器這篇 web.dev 上的文章提供了一個(gè)很好的案例,并提供了相關(guān)的指導(dǎo)原則:

  • 當(dāng)使用你的庫(kù)時(shí),能夠讓開(kāi)發(fā)者去支持老版本的瀏覽器。
  • 輸出多個(gè)產(chǎn)出來(lái)支持不同版本的瀏覽器。

舉個(gè)例子,如果你使用 TypeScript,你可以創(chuàng)建兩個(gè)版本的包代碼:

  • 通過(guò)在tsconfig.json 中設(shè)置 "target"="esnext",生成一個(gè)用現(xiàn)代 JavaScript 的 esm 版本
  • 通過(guò)在tsconfig.json 中設(shè)置 "target"="es5" 生成一個(gè)兼容低版本 JavaScript 的 umd 版本

有了這些設(shè)置,大多數(shù)用戶將獲得現(xiàn)代版本的代碼,但那些使用老的打包工具配置或使用 <script> 加載代碼的用戶,將獲得進(jìn)行了額外編譯來(lái)支持老版本瀏覽器的版本。

必要的編譯

編譯 TypeScript、將 JSX 轉(zhuǎn)換為函數(shù)調(diào)用。

如果庫(kù)的源碼是需要進(jìn)行編譯的形式,如 TypeScript、React 或 Vue 組件等,那么你庫(kù)需要輸出的是編譯后的代碼。

例如:

  • 你的 TypeScript 代碼應(yīng)該輸出為 JavaScript。
  • 你的 React 組件,例如<Example />,應(yīng)該在輸出中使用 jsx() 或 createElement() 來(lái)替換 JSX 語(yǔ)法。

進(jìn)行這樣的編譯時(shí),請(qǐng)確保同時(shí)也創(chuàng)建 sourcemap

維護(hù) changelog

記錄更新和變更。

只要能讓開(kāi)發(fā)者了解到有哪些變更和對(duì)他們的影響,至于是通過(guò)自動(dòng)化工具還是通過(guò)親自動(dòng)手的方式來(lái)處理,這都無(wú)關(guān)緊要。理想情況下,庫(kù)的每次版本變更都應(yīng)該在 changelog 中進(jìn)行相應(yīng)的更新。

拆分出你的 CSS 文件

讓開(kāi)發(fā)者能夠按需引入 CSS。

如果你正在創(chuàng)建一個(gè) CSS 庫(kù)(如 Bootstrap、Tailwind 等),最簡(jiǎn)單的方式就是提供單一文件,包含庫(kù)的所有功能。然而,在這種情況下,你的 CSS 產(chǎn)出最終可能會(huì)變得很大,影響開(kāi)發(fā)者網(wǎng)站的性能。為了避免這種情況,庫(kù)通常會(huì)提供自定義生成 CSS 產(chǎn)出的功能,讓產(chǎn)出中只包含開(kāi)發(fā)者正在使用的必要 CSS(例如,參考 Bootstrap 和 Tailwind 是怎么做的)。

如果 CSS 只是你的庫(kù)的一部分(例如,具有默認(rèn)樣式的組件庫(kù)),那么最好將 CSS 按組件分離單獨(dú)構(gòu)建產(chǎn)出,在使用相應(yīng)的組件時(shí)按需導(dǎo)入。這方面的一個(gè)例子是 react-component。

配置 package.json

package.json 中有許多重要的配置字段值得討論;我在這里將著重討論其中最為重要的一些,這還有很多額外的字段,你同樣可以進(jìn)行配置。

設(shè)置 name 字段

給你的庫(kù)取一個(gè)名:

name? 字段將決定你的包在 npm 上的名字,開(kāi)發(fā)者可以通過(guò)這個(gè)名字去安裝并使用你的庫(kù)。

注意,庫(kù)的命名是有限制的,如果你的代碼庫(kù)屬于某個(gè)組織,你還可以創(chuàng)建一個(gè)命名空間。更多細(xì)節(jié)可以參考 name docs on npm。

name 和 version 的組合為庫(kù)每次迭代創(chuàng)建一個(gè)唯一標(biāo)識(shí)。

設(shè)置 version 字段

通過(guò)更改 version 來(lái)對(duì)你的庫(kù)發(fā)布更新:

正如 name 部分所說(shuō),name? 和 version? 的組合為你的庫(kù)在 npm 上創(chuàng)建一個(gè)唯一標(biāo)識(shí)。當(dāng)你更新庫(kù)中的代碼時(shí),你可以更新 version 字段并發(fā)布以允許開(kāi)發(fā)者獲取該新代碼。

推薦使用 semver 版本控制策略,但要注意的是有些庫(kù)選擇 calver 或使用他們自己特有的版本控制策略。無(wú)論你選擇使用哪種策略,都應(yīng)該記錄下來(lái),以便開(kāi)發(fā)者了解你的庫(kù)是如何進(jìn)行版本控制的。

你還應(yīng)該在 changelog 中記錄你的更改。

定義你的 exports

exports 為你的庫(kù)定義公共 API:

package.json? 中的 exports 字段 - 有時(shí)被稱為“package exports” - 是一個(gè)非常有用的補(bǔ)充,盡管它確實(shí)引入了一些復(fù)雜性。它做的最重要的兩件事是:

  • 定義哪些東西可以從你的庫(kù)中導(dǎo)入,哪些則不可以,以及可導(dǎo)入的內(nèi)容的名字。如果沒(méi)有在exports 中被列出,那么開(kāi)發(fā)者就不可以 import 或 require 它們。換句話說(shuō),exports 的表現(xiàn)像是給你的庫(kù)用戶查看的公共 API,幫助定義哪些是外部的哪些是內(nèi)部的。
  • 允許你根據(jù)不同的條件(你可以定義)去選擇那個(gè)文件是被導(dǎo)入的,例如“文件是被import 還是被 require?開(kāi)發(fā)人員需要的是 development 版本的庫(kù)還是 production 版本等等。

關(guān)于這部分的內(nèi)容NodeJS 團(tuán)隊(duì)和Webpack 團(tuán)隊(duì)提供了一些很優(yōu)秀的文檔。在此我列出一個(gè)涵蓋大部分常見(jiàn)場(chǎng)景的例子:

{
"exports": {
".": {
"types": "index.d.ts",
"module": "index.js",
"import": "index.js",
"require": "index.cjs",
"default": "index.js"
},
"./package.json": "./package.json"
}
}

讓我們深入了解這些字段的含義以及我選擇這個(gè)例子的原因:

  • "." 表示你的庫(kù)的默認(rèn)入口
  • 解析過(guò)程是「從上往下」的,并在找到匹配的字段后立即停止;所以入口的順序是非常重要的
  • types 字段應(yīng)始終放在第一位,幫助 TypeScript 查找類型文件
  • module? 是一個(gè)“非官方”字段,它被 Webpack 和 Rollup 等打包工具所支持。它應(yīng)該被放在 import 和 require 之前,并且指向 esm 格式的產(chǎn)出 -- 如果你的源代碼是純 esm 的,它也可以指向你的源代碼。正如在格式部分中指出的那樣,它旨在幫助打包工具只包含你的庫(kù)的一個(gè)副本,無(wú)論它是通過(guò) import 還是 require 方式引入的。
  • import? 用于當(dāng)有人通過(guò) import 使用你的庫(kù)時(shí)
  • require? 用于當(dāng)有人通過(guò) require 使用你的庫(kù)時(shí)
  • default 字段用于兜底,在沒(méi)有任何條件匹配時(shí)使用。雖然目前可能并不會(huì)匹配到它,但為了面對(duì)“未知的未來(lái)場(chǎng)景”,使用它是好的

當(dāng)一個(gè)打包工具或者運(yùn)行時(shí)支持 exports? 字段的時(shí)候,那么 package.json? 中的頂級(jí)字段 main、types、module 還有 browser 將被忽略,被 exports? 取代。但是,對(duì)于尚不支持 exports 字段的工具或運(yùn)行時(shí)來(lái)說(shuō),設(shè)置這些字段仍然很重要。

如果你有一個(gè) "development" 和一個(gè) "production" 的產(chǎn)出(例如,你有一些警告在 development 產(chǎn)出中有但在 production 產(chǎn)出中沒(méi)有),那么你可以通過(guò)在 exports? 字段中 "development"? 和 "production"? 來(lái)設(shè)置它們。注意一些打包工具例如 webpack? 和 vite 將會(huì)自動(dòng)識(shí)別這些導(dǎo)出條件,而 Rollup 也可以通過(guò)配置來(lái)識(shí)別它們,你需要提醒開(kāi)發(fā)者在他們自己打包工具的配置中去做這些事。

列出要發(fā)布的 files

files 定義你的 NPM 包中要包含哪些文件:

files? 決定 npm CLI 在打包庫(kù)時(shí)哪些文件和目錄包含到最終的 NPM 包中。

例如,如果你將代碼從 TypeScript 編譯為 JavaScript,你可能就不想在 NPM 包中包含 TypeScript 的源代碼。(相反,你應(yīng)該包含 sourcemap)。

files 可以接受一個(gè)字符串?dāng)?shù)組(如果需要,這些字符串可以包含類似 glob 的語(yǔ)法),例如:

{
"files": ["dist"]
}

注意,文件數(shù)組不接受相對(duì)路徑表示;"files": ["./dist"] 將無(wú)法正常工作。

驗(yàn)證你已正確設(shè)置 files? 的一種好方法是運(yùn)行 npm publish --dry-run,它將根據(jù)此設(shè)置列出將會(huì)包含的文件。

為你的 JS 文件設(shè)置默認(rèn)的模塊 type

type? 規(guī)定你的 .js 文件使用哪個(gè)模塊系統(tǒng):

運(yùn)行時(shí)和打包工具需要一種方法來(lái)確定你的 .js? 文件采用哪種模塊系統(tǒng) —— ESM 還是 CommonJS。因?yàn)?CommonJS 首先出現(xiàn),所以它被打包工具視為默認(rèn)的 - 但你可以通過(guò)在你的 package.json? 中添加 "type" 來(lái)控制這種行為。

你可以選擇 "type":"module"? 或 "type":"commonjs",也可以不添加該字段(默認(rèn)為 CommonJS),但仍強(qiáng)烈建議你進(jìn)行設(shè)置,顯式地聲明你正在使用哪一個(gè)。

請(qǐng)注意,你可以通過(guò)幾個(gè)技巧在項(xiàng)目中混用模塊類型:

  • .mjs? 文件總是 ESM 模塊,即使你的 package.json 有 "type": "commonjs"(或者沒(méi)有 type)
  • .cjs? 文件總是 CommonJS 模塊,即使你的 package.json 有 "type": "module"
  • 你可以在子目錄下添加其他package.json 文件;運(yùn)行時(shí)和打包工具將向上遍歷文件目錄,直到尋找到最近的 package.json。這意味著你可以有兩個(gè)不同的文件夾,都使用 .js 文件,但每個(gè)文件夾都有自己的 package.json 并設(shè)置為不同的 type 以獲得基于 CommonJS 和 ESM 的文件夾。

列出哪些模塊有 sideEffects

設(shè)置 sideEffects 來(lái)允許 treeshaking:

創(chuàng)建一個(gè)“純模塊”帶來(lái)的優(yōu)點(diǎn)與創(chuàng)建一個(gè)純函數(shù)十分類似;打包工具能夠?qū)δ愕膸?kù)更好的進(jìn)行 treeshaking。

通過(guò)設(shè)置 sideEffects 讓打包工具知道你的模塊是否是“純”的。不設(shè)置這個(gè)字段,打包工具將不得不假設(shè)你「所有」的模塊都是有副作用。

sideEffects? 可以設(shè)為 false,表示沒(méi)有任何模塊具有副作用,也可以設(shè)置為字符串?dāng)?shù)組來(lái)列出哪些文件具有副作用。例如:

{
// 所有模塊都是“純”的
"sideEffects": false
}

或:

{
// 除了 "module.js",所有模塊都是“純”的
"sideEffects": ["module.js"]
}

所以,什么讓一個(gè)模塊具有副作用?例如修改一個(gè)全局變量,發(fā)送 API 請(qǐng)求,或?qū)С?CSS,而且開(kāi)發(fā)人員不需要做任何事情這些動(dòng)作就會(huì)被執(zhí)行。例如:

// 具有副作用的模塊

export const myVar = "hello";

window.example = "testing";

導(dǎo)入 myVar? 時(shí),你的模塊自動(dòng)設(shè)置 window.example。

例如:

import { myVar } from "library";

console.log(window.example);
// 打印 "testing"

在某些情況下,如 polyfill,這種行為是有意的。然而,如果我們想讓這個(gè)模塊是“純”的,我們可以將對(duì) window.example 的賦值移動(dòng)到一個(gè)函數(shù)中。例如:

// 一個(gè)“純”模塊

export const myVar = "hello";

export function setExample() {
window.example = "testing";
}

現(xiàn)在這是一個(gè)“純”模塊。注意,從開(kāi)發(fā)者的角度來(lái)看會(huì)有不同:

import { myVar, setExample } from "library";

console.log(window.example);
// 打印 "undefined"

setExample();

console.log(window.example);
// 打印 "testing"

設(shè)置 main 字段

main 定義 CommonJS 入口:

main? 是一個(gè)當(dāng)打包工具或運(yùn)行時(shí)不支持 package.json#exports? 時(shí)的兜底方案;如果打包工具或運(yùn)行時(shí)支持 package exports,則不會(huì)使用 main。

main? 應(yīng)該指向一個(gè)兼容 CommonJS 格式的產(chǎn)出;它應(yīng)該與 package exports 中的 require 保持一致。

設(shè)置 module 字段

module 定義 ESM 入口:

module? 是一個(gè)當(dāng)打包工具或運(yùn)行時(shí)不支持 package.json#exports? 時(shí)的兜底方案;如果打包工具或運(yùn)行時(shí)支持 package exports,則不會(huì)使用 module。

module? 應(yīng)該指向一個(gè)兼容 ESM 格式的產(chǎn)出;它應(yīng)該與 package exports 中的 module? 或 import 保持一致。

設(shè)置給 CDN 使用的附加字段

支持 CDN,例如 unpkg? 和 jsdelivr:

為讓你的庫(kù)在 CDN 上“以默認(rèn)的方式正常工作”,如 unpkg 和 jsdelivr,你可以設(shè)置它們的特定字段指向你的 umd 產(chǎn)出。例如:

{
"unpkg": "./dist/index.umd.js",
"jsdelivr": "./dist/index.umd.js"
}

設(shè)置 browser 字段

browser 指向能在瀏覽器中工作的產(chǎn)出:

browser? 是一個(gè)當(dāng)打包工具或運(yùn)行時(shí)不支持 package.json#exports? 時(shí)的兜底方案;如果打包工具或運(yùn)行時(shí)支持 package exports, 則不會(huì)使用 browser。

browser? 應(yīng)該指向能在瀏覽器中工作的 esm? 產(chǎn)出。但是,只有在為瀏覽器和服務(wù)器(等其他非瀏覽器環(huán)境)創(chuàng)建不同的產(chǎn)出時(shí),才需要設(shè)置該字段。如果你沒(méi)有為多個(gè)環(huán)境創(chuàng)建多個(gè)產(chǎn)出,或者你的產(chǎn)出是“純 JavaScript”或“通用”的,可以在任何 JavaScript 環(huán)境中運(yùn)行,那么你就不需要設(shè)置 browser 字段。

如果你確實(shí)需要設(shè)置該字段,這里有一個(gè)優(yōu)秀的指南,介紹了配置它的不同方法。

注意,browser? 字段不應(yīng)該指向 umd 產(chǎn)出,因?yàn)槟菢拥脑挘愕膸?kù)就不會(huì)被打包工具(如 Webpack)進(jìn)行 treeshaking,這些打包工具會(huì)優(yōu)先考慮這個(gè)字段,而不是其他字段,比如 module 和 main。

設(shè)置 types 字段

types 定義 TypeScript 類型:

types? 是一個(gè)當(dāng)打包工具或運(yùn)行時(shí)不支持 package.json#exports? 時(shí)的兜底方案;如果打包工具或運(yùn)行時(shí)支持 package exports,則不會(huì)使用 types。

types? 應(yīng)該指向你的 TypeScript 入口文件,例如 index.d.ts?;它應(yīng)該與 package exports 中的 types 字段指向同一個(gè)文件。

列出 peerDependencies

如果你依賴別的框架或庫(kù),將它設(shè)置為 peer dependency:

你應(yīng)該外置框架。然而,這樣做后,你的庫(kù)只有在開(kāi)發(fā)人員自行安裝你需要的框架后才能工作。設(shè)置 peerDependencies 讓他們知道他們需要安裝的框架。- 例如,如果你在創(chuàng)建一個(gè) React 庫(kù):

{
"peerDependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}

你應(yīng)該以書(shū)面形式來(lái)體現(xiàn)這些依賴;例如,npm v3-v6? 不安裝 peer dependencies,而 npm v7+ 將自動(dòng)安裝 peer dependencies。

說(shuō)明你的庫(kù)使用哪個(gè)許可證

保護(hù)你自己和其他的貢獻(xiàn)者:

開(kāi)源許可證用于保護(hù)貢獻(xiàn)者和用戶。沒(méi)有這種保護(hù),企業(yè)和有經(jīng)驗(yàn)的開(kāi)發(fā)者不會(huì)使用該項(xiàng)目。

上述引用自 Choose a License,這也是一篇很好的文章,幫助你來(lái)決定哪個(gè)許可證適合你的項(xiàng)目。

當(dāng)你決定了許可證,關(guān)于許可證的 npm 文檔中描述了許可證字段的格式。例如:

{
"license": "MIT"
}

除此之外,你可以在項(xiàng)目的根目錄下創(chuàng)建一個(gè) LICENSE.txt 文件,并將許可證的文本復(fù)制到這里。

責(zé)任編輯:趙寧寧 來(lái)源: code秘密花園
相關(guān)推薦

2021-06-03 09:31:56

React狀態(tài)模式

2025-07-14 09:47:56

2024-11-07 22:58:33

2010-12-23 13:44:10

Windows 7桌面部署

2021-07-09 05:25:48

CIO遺留系統(tǒng)現(xiàn)代化用戶體驗(yàn)

2022-10-09 09:30:33

CSS瀏覽器十六進(jìn)制

2025-08-08 07:18:00

CIOIT架構(gòu)IT服務(wù)管理

2022-07-03 08:06:40

JavaScript語(yǔ)言代碼

2024-05-30 08:01:52

2019-11-05 16:51:41

JavaScript數(shù)據(jù)es8

2017-01-12 14:55:50

JavaScript編程

2016-04-25 10:23:52

2022-11-03 07:48:27

CSSat-rule

2023-05-08 09:00:46

JSON深拷貝對(duì)象

2025-02-14 08:26:39

2011-08-09 09:48:20

JavaScript

2013-08-01 14:03:49

JavaScript

2021-05-07 21:53:44

Python 程序pyinstaller

2021-05-08 12:30:03

Pythonexe代碼

2011-12-07 12:01:31

ibmdw
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

ijzzijzzij亚洲大全| 久久综合久久色| 超碰97在线免费| 精品9999| 欧美大黄免费观看| 青青青免费视频在线2| 先锋影音久久| 国产精品扒开腿爽爽爽视频| 精品国内二区三区| 精品国产综合久久| 激情av综合| 亚洲欧美一区二区三区情侣bbw| 精品亚洲成a人片在线观看| 国产农村妇女毛片精品久久麻豆 | 国产日韩欧美一区二区三区| 亚洲香蕉成人av网站在线观看 | 成人av综合一区| 国产精品视频久久| 国产精品xnxxcom| 日韩电影免费观看在线观看| 二区在线视频| 一区二区在线电影| 欧美 日韩 国产一区| 精品一区二区三区不卡| 亚洲一区国产精品| 99久久激情| 国产在线高清精品| 欧美黑人巨大videos精品| 欧美极品美女视频网站在线观看免费 | 污网站在线播放| 久久综合色播五月| 亚洲精品人成| 999国产精品999久久久久久| 97视频在线看| 亚洲精华液一区二区三区| 亚洲国产精品成人av| 视频一区二区三区在线看免费看| 亚洲最大的成人av| 最近中文字幕mv第三季歌词| 久久99精品国产麻豆不卡| 欧美美乳视频网站在线观看| 在线成人超碰| 久久久久资源| 一区二区免费不卡在线| 高清国产在线一区| 99av国产精品欲麻豆| 日韩中文字幕av在线| 国产成人在线免费观看| 亚洲人成无码www久久久| 中文字幕视频一区二区三区久| 天天操夜夜干| 91 com成人网| 波多一区二区| 中文字幕日韩免费视频| 国产精品自在线拍| 成人国内精品久久久久一区| 在线精品观看| 欧美日韩免费观看一区| 国产一区二区三区在线观看精品| 国精产品一区一区三区视频| 一区二区三区中文字幕在线观看| 成全电影播放在线观看国语| 欧美精品一区二区三区蜜臀 | 日韩第二十一页| 国产精品久久久久久久久免费看| 国语精品一区| av磁力番号网| 亚洲人成小说网站色在线 | 日韩一区二区三区高清免费看看 | 精品视频免费在线播放| 亚洲女同一区二区| 久久99精品久久久久久野外| 中文字幕久久久av一区| 亚洲国产欧美日韩在线观看第一区| 亚洲在线免费观看| 在线一区视频| 无码内射中文字幕岛国片| 亚洲午夜成aⅴ人片| www.综合| 欧美最猛性xxxxx(亚洲精品)| 日韩夫妻性生活xx| 在线精品亚洲一区二区| 亚洲精品乱码久久久久久久久| 男人资源网站| 精品亚洲夜色av98在线观看| 精品久久久久久久| 日产中文字幕在线精品一区| 国产亚洲一区二区三区四区| 情趣网站视频在线观看| 亚洲精品99久久久久| 日韩影视在线观看| 综合视频免费看| 欧美日韩中文字幕在线视频| 99久久er| 狠狠干一区二区| 18欧美乱大交hd1984| 国产精品一品| 在线播放日韩欧美| 国产精品最新| 免费观看国产视频在线| 一本色道**综合亚洲精品蜜桃冫| 123成人网| 精品视频一区二区| 亚洲精品五月天| 中文字幕21页在线看| 91精品在线影院| 国产精品入口麻豆原神| 影音先锋在线视频| 国产精品一区二区性色av| 成人av影院在线| 精品精品导航| 国产一区二区三区色淫影院| 悠悠色在线精品| 日韩一二三区在线观看| av动漫在线播放| 在线91免费看| 欧美一区二区三区高清视频| 国模吧无码一区二区三区| 亚洲成人黄色网址| 欧美 亚欧 日韩视频在线 | 欧美激情综合在线| 国外成人福利视频| 樱花www成人免费视频| 色8久久人人97超碰香蕉987| 日韩综合一区二区三区| 中文字幕超清在线免费观看| 亚洲六月丁香色婷婷综合久久 | 亚洲一区电影777| 性国裸体高清亚洲| 国产成人久久久精品一区| 欧美韩国一区二区| 麻豆国产一区| 欧美 日韩 国产精品| 色婷婷亚洲一区二区三区| 一区二区三区高清在线观看| 男人j进女人j| 中文字幕亚洲一区| 国产真实有声精品录音| 欧美日韩高清免费| 日韩精品一区二区三区视频播放 | 国产免费一区二区| 欧美人体做爰大胆视频| 亚洲伊人观看| 美女航空一级毛片在线播放| 色之综合天天综合色天天棕色| 五月激情综合色| 欧美jjzz| 草美女在线观看| 久久久久久久久久久久久国产| 精品av久久707| www.欧美色图| **爰片久久毛片| 日本韩国在线视频| 国产精品久久久一区二区三区| 欧美视频一区二区在线观看| 美腿丝袜亚洲色图| 色呦呦在线看| 欧美在线观看黄| 国内精品400部情侣激情| 亚洲一区二区美女| 免费亚洲一区| 一区二区精品伦理...| 天天操天天摸天天爽| 亚洲精品日产aⅴ| 精品香蕉一区二区三区| 91色九色蝌蚪| 久久影院一区| 牛牛精品一区二区| 精品久久久久久无码国产| 91九色单男在线观看| 日韩av网站导航| 久久久久久电影| 黄色免费成人| 二区三区不卡| 成人网址大全| 国产亚洲自拍偷拍| 精品国内亚洲在观看18黄| 欧美午夜电影在线| 国内精品久久久久影院薰衣草| 超碰在线成人| 在线三级电影| 亚洲第一狼人区| 欧美在线激情| …久久精品99久久香蕉国产| 亚洲精品一区二区三区99| 久久亚洲精品小早川怜子| 午夜性色一区二区三区免费视频| 成人自拍视频网| 又黄又www的网站| 麻豆一区二区三区在线观看| 国产精品美女主播| 日韩有码片在线观看| 色呦呦国产精品| 中文字幕国产精品一区二区| 影音国产精品| 久久99国产精品久久99大师| 91在线中字| 亚洲伦理在线| 五月婷婷导航| 欧美黑人在线观看|