」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 為具有 ESM 依賴項的 CommonJS 建置 NPM 包

為具有 ESM 依賴項的 CommonJS 建置 NPM 包

發佈於2024-08-14
瀏覽:424

Building NPM packages for CommonJS with ESM dependencies

總長DR

您必須使用諸如 esbuild 之類的打包程序,它將編譯您的專案並將其所有依賴項與其一起打包,這樣它們就不會被導入。這繞過了 ESM/CommonJS 不相容問題。

如果你不耐煩,可以直接看這個範例實現的程式碼。

情境

在周末準備發布我的新專案 Token.js 時,我遇到了一個非常令人沮喪的問題。我希望我的包除了 ESM 之外還支援 CommonJS,但我有純粹的 ESM 依賴項。純粹的 ESM 鬥士們可能對我這麼說很不高興,但如果你正在建造一個 NPM 包並希望它被廣泛使用,你仍然需要在 2024 年支持 CommonJS。

Token.js 是一個簡單的 TypeScript SDK,可讓您整合來自 9 個不同提供者(OpenAI、Anthropic、Cohere 等)的 60 個 LLM。無恥的插件,如果你喜歡產生人工智慧,請檢查一下並告訴我你的想法。

現在有許多線上資源討論如何為 ESM、CommonJS 或兩者建立 Javascript 專案。然而,我特別難以處理這樣一個事實:我有純 ESM 的依賴項。我發現這很難處理,因為我不熟悉捆綁程式(我主要從事 Web 應用程式後端),也無法找到有關該主題的良好指南。

因此,如果其他人遇到此問題,這裡是解決方案。

指導

安裝esbuild

我們將使用 esbuild 作為捆綁器。

yarn add esbuild --save-dev

建立建置腳本

我們需要一個簡單的建置腳本來執行 esbuild 並輸出結果。

import esbuild from 'esbuild'

const entrypoint = ""
const tsconfig = ""

const build = async () => {
  await Promise.all([
    // bundle for commonjs
    esbuild.build({
      entryPoints: [entrypoint],
      bundle: true,
      minify: true,
      format: 'cjs',
      outfile: `./dist/index.cjs`,
      platform: 'node',
      treeShaking: true,
      tsconfig,
    }),
  ])
}

build()

將建置腳本新增至 package.json

使用您首選的運行時運行。

"scripts": {
  "build": "vite-node ./scripts/build.ts",
}

我個人很喜歡vite-node。因此,如果您想完全遵循,則需要安裝:

yarn add vite-node --save-dev

建立您的專案

yarn build

這將導致使用 esbuild 建立您的項目,您將看到一個新檔案 dist/index.cjs,它是您的套件的 CommonJS 建置。

配置入口點

更新您的 package.json 以指向您的 CommonJS 入口點。

"main": "dist/index.cjs",

嘭!現在,您已經為 CommonJS 建立了套件。即使您有 ESM 依賴項,這也將起作用,因為依賴項將被捆綁
連同您的包裹。

由於呼叫 esbuild 時存在欄位“bundle: true”,因此依賴項包含在輸出中。

TypeScript 聲明

雖然技術上不需要,但您很可能還需要 TypeScript 聲明,遺憾的是 esbuild 目前無法輸出這些聲明。所以生成
那些,你會想要使用普通的 tsc。

更新您的 tsconfig.json

將這些選項新增至 tsconfig.json 檔案將導致僅輸出 TypeScript 聲明。這正是我們想要的,因為包的其餘部分
正在使用 esbuild 建置。

"declaration": true,
"declarationDir": "./dist",
"emitDeclarationOnly": true

更新您的建置腳本

"scripts": {
  "build:tsc": "yarn tsc -p tsconfig.json",
  "build": "vite-node ./scripts/build.ts && yarn build:tsc",
}

雙入口點

本指南建議僅為您的包輸出單一 CommonJS 入口點。就我個人而言,我認為這是最好的選擇,原因有兩個:

  • 最小化捆綁包大小
  • 避免雙重包裝危險

然而,這不是唯一的選擇。您也可以使用 CommonJS 和 ESM 的雙入口點發布包。

更新您的建置腳本以包含 ESM 構建

import esbuild from 'esbuild'

const entrypoint = ""
const tsconfig = ""

const build = async () => {
  await Promise.all([
    // bundle for commonjs
    esbuild.build({
      entryPoints: [entrypoint],
      bundle: true,
      minify: true,
      format: 'cjs',
      outfile: `./dist/index.cjs`,
      platform: 'node',
      treeShaking: true,
      tsconfig,
    }),
    // bundle for ESM
    esbuild.build({
      entryPoints: [entrypoint],
      bundle: true,
      minify: true,
      format: 'esm',
      outfile: `./dist/index.js`,
      platform: 'node',
      treeShaking: true,
      tsconfig,
    }),
  ])
}

build()

更新您的 package.json 檔案以包含雙入口點

"main": "dist/index.cjs",
"module": "dist/index.js",
"type": "module",
"exports": {
  ".": {
    "import": "./dist/index.js",
    "require": "./dist/index.cjs",
    "types": "./dist/index.d.ts"
  }
},

原始碼

版本聲明 本文轉載於:https://dev.to/ryan_pate_f494c0931176673/how-to-build-npm-packages-for-commonjs-with-pure-esm-dependencies-38jm?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 如何從Google API中檢索最新的jQuery庫?
    如何從Google API中檢索最新的jQuery庫?
    從Google APIS 問題中提供的jQuery URL是版本1.2.6。對於檢索最新版本,以前有一種使用特定版本號的替代方法,它是使用以下語法: https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js(google hosted...
    程式設計 發佈於2025-02-07
  • \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    \“(1)vs.(;;):編譯器優化是否消除了性能差異?\”
    使用(1)而不是(;;)會導致無限循環的性能差異? 現代編譯器,(1)和(;;)之間沒有性能差異。 是如何實現這些循環的技術分析在編譯器中: perl: S-> 7 8 unstack v-> 4 -e語法ok 在GCC中,兩者都循環到相同的彙編代碼中,如下所示:。 globl t_時 ...
    程式設計 發佈於2025-02-07
  • 如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    如何從Python中的字符串中刪除表情符號:固定常見錯誤的初學者指南?
    從python 導入編解碼器 導入 text = codecs.decode('這狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#帶有表情符號 emoji_pattern = re.compile(“ [”...
    程式設計 發佈於2025-02-07
  • 大批
    大批
    [2 數組是對象,因此它們在JS中也具有方法。 切片(開始):在新數組中提取部分數組,而無需突變原始數組。 令arr = ['a','b','c','d','e']; // USECASE:提取直到索引作...
    程式設計 發佈於2025-02-07
  • 如何使用FormData()處理多個文件上傳?
    如何使用FormData()處理多個文件上傳?
    )處理多個文件輸入時,通常需要處理多個文件上傳時,通常是必要的。可以將fd.append("fileToUpload[]", files[x]);方法用於此目的,允許您在單個請求中發送多個文件。 初始嘗試 在JavaScript中,一種常見方法是:); 但是,此代碼僅處理第...
    程式設計 發佈於2025-02-07
  • 如何使用PHP將斑點(圖像)正確插入MySQL?
    如何使用PHP將斑點(圖像)正確插入MySQL?
    在嘗試將image存儲在mysql數據庫中時,您可能會遇到一個可能會遇到問題。本指南將提供成功存儲您的圖像數據的解決方案。 easudy values('$ this-> ; image_id','file_get_contents($ tmp_imag...
    程式設計 發佈於2025-02-07
  • 為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    為什麼Microsoft Visual C ++無法正確實現兩台模板的實例?
    [2明確擔心Microsoft Visual C(MSVC)在正確實現兩相模板實例化方面努力努力。該機制的哪些具體方面無法按預期運行? 背景:說明:的初始Syntax檢查在範圍中受到限制。它未能檢查是否存在聲明名稱的存在,導致名稱缺乏正確的聲明時會導致編譯問題。 為了說明這一點,請考慮以下示例:一個...
    程式設計 發佈於2025-02-07
  • 如何有效地從GO中的字符串中剝離所有空格?
    如何有效地從GO中的字符串中剝離所有空格?
    在GO中有效地剝離whitespace:找到最佳解決方案問題:我如何迅速從go中的任意字符串中迅速剝離所有空格?我已經嘗試了鏈接strings.fields()and strings.join()函數,但我懷疑有一個更有效的方法。 隨機串:=“這是一個測試” fmt.println(strings...
    程式設計 發佈於2025-02-07
  • 如何使用PHP從XML文件中有效地檢索屬性值?
    如何使用PHP從XML文件中有效地檢索屬性值?
    從php 您的目標可能是檢索“ varnum”屬性值,其中提取數據的傳統方法可能會使您感到困惑。 - > attributes()為$ attributeName => $ attributeValue){ echo $ attributeName,'=“',$ a...
    程式設計 發佈於2025-02-07
  • 哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
    哪種方法更有效地用於點 - 填點檢測:射線跟踪或matplotlib \的路徑contains_points?
    在Python 射線tracing方法Matplotlib's path.contains_points FunctionMatplotlib's path.contains_points function employs a路徑對象表示多邊形。它檢查給定點是否位於定義路徑內。 T...
    程式設計 發佈於2025-02-07
  • 如何克服PHP的功能重新定義限制?
    如何克服PHP的功能重新定義限制?
    克服PHP的函數重新定義限制在PHP中,多次定義一個相同名稱的函數是一個no-no。嘗試這樣做,如提供的代碼段所示,將導致可怕的“不能重新列出”錯誤。 // error:“ coss redeclare foo()” 但是,php工具腰帶中有一個隱藏的寶石:runkit擴展。它使您能夠靈活...
    程式設計 發佈於2025-02-07
  • Java是否允許多種返回類型:仔細研究通用方法?
    Java是否允許多種返回類型:仔細研究通用方法?
    在java中的多個返回類型:一個誤解介紹,其中foo是自定義類。該方法聲明似乎擁有兩種返回類型:列表和E。但是,情況確實如此嗎? 通用方法:拆開神秘 [方法僅具有單一的返回類型。相反,它採用機制,如鑽石符號“ ”。 分解方法簽名: :本節定義了一個通用類型參數,E。它表示該方法接受了擴展foo類...
    程式設計 發佈於2025-02-07
  • 在沒有密碼提示的情況下,如何在Ubuntu上安裝MySQL?
    在沒有密碼提示的情況下,如何在Ubuntu上安裝MySQL?
    在ubuntu 使用debconf-set-selections sudo debconf-set-selections
    程式設計 發佈於2025-02-07
  • 如何在Java列表中有效計算元素的發生?
    如何在Java列表中有效計算元素的發生?
    計數列表中的元素出現在列表 中,在java編程中,列舉列表中列舉元素出現的任務來自列表。為此,收集框架提供了全面的工具套件。 在這種情況下,Batocurrences變量將保持值3,代表動物列表中的“ BAT”出現的數量。 &&& [此方法是簡單的,可以得出準確的結果,使其成為計算列表中元素出現的...
    程式設計 發佈於2025-02-07
  • 如何限制動態大小的父元素中元素的滾動範圍?
    如何限制動態大小的父元素中元素的滾動範圍?
    在交互式界面中實現垂直滾動元素的CSS高度限制 考慮一個佈局,其中我們具有與可滾動的映射div一起移動的subollable map div用戶的垂直滾動,同時保持其與固定側邊欄的對齊方式。但是,地圖的滾動無限期擴展,超過了視口的高度,阻止用戶訪問頁面頁腳。 可以限制地圖的滾動,我們可以利用CS...
    程式設計 發佈於2025-02-07

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3