Heim  >  Artikel  >  Web-Frontend  >  Erstellen von NPM-Paketen für CommonJS mit ESM-Abhängigkeiten

Erstellen von NPM-Paketen für CommonJS mit ESM-Abhängigkeiten

PHPz
PHPzOriginal
2024-07-18 13:43:15531Durchsuche

Building NPM packages for CommonJS with ESM dependencies

TLDR

Sie müssen einen Bundler wie esbuild verwenden, der Ihr Projekt kompiliert und alle seine Abhängigkeiten bündelt, damit sie nicht importiert werden. Dadurch wird das ESM/CommonJS-Inkompatibilitätsproblem umgangen.

Wenn Sie ungeduldig sind, können Sie mit dieser Beispielimplementierung direkt zum Code gehen.

Kontext

Als ich mich am Wochenende auf die Veröffentlichung meines neuen Projekts Token.js vorbereitete, stieß ich auf ein ziemlich frustrierendes Problem. Ich wollte, dass mein Paket zusätzlich zu ESM auch CommonJS unterstützt, aber ich hatte reine ESM-Abhängigkeiten. Die reinen ESM-Kreuzfahrer da draußen mögen ziemlich unzufrieden sein, wenn ich das sage, aber wenn Sie ein NPM-Paket erstellen und möchten, dass es weit verbreitet ist, müssen Sie CommonJS im Jahr 2024 noch unterstützen.

Token.js ist ein einfaches TypeScript-SDK, mit dem Sie mehr als 60 LLMs von 9 verschiedenen Anbietern (OpenAI, Anthropic, Cohere usw.) integrieren können. Shameless Plug, schau es dir an und lass mich wissen, was du denkst, wenn du dich für generative KI interessierst.

Jetzt gibt es online eine Reihe von Ressourcen, die diskutieren, wie man Javascript-Projekte für ESM, CommonJS oder beide erstellt. Allerdings hatte ich insbesondere Probleme damit, mit der Tatsache umzugehen, dass ich Abhängigkeiten hatte, die reines ESM waren. Es fiel mir ziemlich schwer, damit umzugehen, da ich mit Bundlern nicht vertraut bin (ich habe hauptsächlich an Webapp-Backends gearbeitet) und keinen guten Leitfaden zu diesem Thema finden konnte.

Wenn also noch jemand auf dieses Problem stößt, finden Sie hier die Lösung.

Führung

Esbuild installieren

Wir werden esbuild für den Bundler verwenden.

yarn add esbuild --save-dev

Erstellen Sie ein Build-Skript

Wir benötigen ein einfaches Build-Skript, um esbuild auszuführen und die Ergebnisse auszugeben.

import esbuild from 'esbuild'

const entrypoint = "<your entrypoint here>"
const tsconfig = "<your tsconfig path here>"

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()

Fügen Sie Ihrer package.json ein Build-Skript hinzu

Mit Ihrer bevorzugten Laufzeit ausführen.

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

Ich persönlich liebe vite-node. Wenn Sie also genau mitmachen möchten, müssen Sie Folgendes installieren:

yarn add vite-node --save-dev

Erstellen Sie Ihr Projekt

yarn build

Dadurch wird Ihr Projekt mit esbuild erstellt und Sie sehen eine neue Datei, dist/index.cjs, die der CommonJS-Build Ihres Pakets ist.

Einstiegspunkt konfigurieren

Aktualisieren Sie Ihre package.json so, dass sie auf Ihren CommonJS-Einstiegspunkt verweist.

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

Bam! Nun haben Sie Ihr Paket für CommonJS erstellt. Dies funktioniert auch dann, wenn Sie ESM-Abhängigkeiten haben, da die Abhängigkeiten gebündelt werden
zusammen mit Ihrem Paket.

Die Abhängigkeiten werden aufgrund des Feldes bundle: true beim Aufruf von esbuild in die Ausgabe einbezogen.

TypeScript-Deklarationen

Obwohl technisch nicht erforderlich, möchten Sie höchstwahrscheinlich auch TypeScript-Deklarationen, die esbuild derzeit leider nicht ausgibt. Also generieren
Für diese sollten Sie normales TSC verwenden.

Aktualisieren Sie Ihre tsconfig.json

Das Hinzufügen dieser Optionen zu Ihrer tsconfig.json-Datei führt dazu, dass nur die TypeScript-Deklarationen ausgegeben werden. Das ist genau das, was wir vom Rest des Pakets wollen
wird mit esbuild erstellt.

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

Aktualisieren Sie Ihr Build-Skript

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

Duale Einstiegspunkte

Diese Anleitung empfiehlt, nur einen einzigen CommonJS-Einstiegspunkt für Ihr Paket auszugeben. Persönlich denke ich, dass dies aus zwei Gründen die beste Option ist:

  • Minimiert die Paketgröße
  • Vermeidet die Gefahr einer doppelten Verpackung

Dies ist jedoch nicht die einzige Option. Sie können Ihr Paket auch mit zwei Einstiegspunkten für CommonJS und ESM veröffentlichen.

Aktualisieren Sie Ihr Build-Skript, um einen ESM-Build einzubinden

import esbuild from 'esbuild'

const entrypoint = "<your entrypoint here>"
const tsconfig = "<your tsconfig path here>"

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()

Aktualisieren Sie Ihre package.json-Datei, um zwei Einstiegspunkte einzuschließen

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

Quellcode

Das obige ist der detaillierte Inhalt vonErstellen von NPM-Paketen für CommonJS mit ESM-Abhängigkeiten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn