「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > ESM 依存関係を使用した CommonJS 用の NPM パッケージの構築

ESM 依存関係を使用した CommonJS 用の NPM パッケージの構築

2024 年 8 月 14 日に公開
ブラウズ:200

Building NPM packages for CommonJS with ESM dependencies

TLDR

プロジェクトをコンパイルし、依存関係がインポートされないようにすべての依存関係をバンドルする esbuild などのバンドラーを使用する必要があります。これにより、ESM/CommonJS の非互換性の問題が回避されます。

せっかちな場合は、この実装例のコードに直接進むことができます。

コンテクスト

週末に新しいプロジェクト Token.js をリリースする準備をしているときに、非常にイライラする問題に遭遇しました。パッケージで ESM に加えて CommonJS もサポートしたいと考えていましたが、純粋な ESM 依存関係がありました。純粋な ESM 活動家たちは、私がこれを言うことに非常に不満を抱いているかもしれませんが、NPM パッケージを構築していて、それを広く使用したい場合は、2024 年になっても CommonJS をサポートする必要があります。

Token.js は、9 つ​​の異なるプロバイダー (OpenAI、Anthropic、Cohere など) の 60 個の LLM を統合できるシンプルな TypeScript SDK です。恥知らずなプラグインです。ぜひチェックして、生成 AI に興味がある方は意見を聞かせてください。

現在、ESM、CommonJS、またはその両方用の Javascript プロジェクトを構築する方法を説明するリソースがオンラインに多数あります。ただし、純粋な ESM の依存関係があるという事実に対処するのに特に問題がありました。私はバンドラーに詳しくなく (主に Web アプリのバックエンドに取り組んできました)、このトピックに関する適切なガイドを見つけることができなかったので、これに対処するのは非常に難しいことがわかりました。

他の誰かがこの問題に遭遇している場合は、ここに解決策があります。

ガイド

エスビルドをインストールする

バンドラーには 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 を使用してプロジェクトがビルドされ、パッケージの CommonJS ビルドである新しいファイル dist/index.cjs が表示されます。

エントリポイントの構成

CommonJS エントリポイントを指すように package.json を更新します。

"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 エントリポイントのみを出力することをお勧めします。個人的には、次の 2 つの理由から、これが最良のオプションだと思います:

  • バンドルのサイズを最小化します
  • 二重パッケージの危険を回避

ただし、これが唯一の選択肢ではありません。 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-dependency-38jm?1 侵害がある場合は、study_golang にご連絡ください。 @163.com 削除
最新のチュートリアル もっと>

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3