Maison  >  Article  >  interface Web  >  Création de packages NPM pour CommonJS avec des dépendances ESM

Création de packages NPM pour CommonJS avec des dépendances ESM

PHPz
PHPzoriginal
2024-07-18 13:43:15531parcourir

Building NPM packages for CommonJS with ESM dependencies

TLDR

Vous devez utiliser un bundler tel que esbuild qui compilera votre projet et regroupera toutes ses dépendances avec lui afin qu'elles ne soient pas importées. Cela contourne le problème d'incompatibilité ESM/CommonJS.

Si vous êtes impatient, vous pouvez accéder directement au code avec cet exemple d'implémentation.

Contexte

En préparant la sortie de mon nouveau projet Token.js ce week-end, j'ai rencontré un problème assez frustrant. Je voulais que mon package prenne en charge CommonJS en plus d'ESM, mais j'avais de pures dépendances ESM. Les purs croisés de l'ESM seront peut-être assez mécontents que je le dise, mais si vous créez un package NPM et souhaitez qu'il soit largement utilisé, vous devez toujours prendre en charge CommonJS en 2024.

Token.js est un simple SDK TypeScript qui vous permet d'intégrer plus de 60 LLM de 9 fournisseurs différents (OpenAI, Anthropic, Cohere, etc.). Plug sans vergogne, jetez-y un œil et dites-moi ce que vous en pensez si vous aimez l'IA générative.

Il existe désormais un certain nombre de ressources en ligne expliquant comment créer des projets Javascript pour ESM, CommonJS ou les deux. Cependant, j'ai particulièrement eu du mal à gérer le fait que j'avais des dépendances qui étaient purement ESM. J'ai trouvé cela assez difficile à gérer car je ne suis pas familier avec les bundlers (j'ai principalement travaillé sur des backends d'applications Web) et je n'ai pas pu trouver un bon guide sur le sujet.

Donc, si quelqu'un d'autre rencontre ce problème, voici la solution.

Guide

Installer esbuild

Nous utiliserons esbuild pour le bundler.

yarn add esbuild --save-dev

Créer un script de build

Nous aurons besoin d'un simple script de build pour exécuter esbuild et afficher les résultats.

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

Ajoutez un script de build à votre package.json

Exécutez avec votre environnement d'exécution préféré.

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

Personnellement, j'adore vite-node. Donc si vous voulez suivre exactement, vous devrez installer ça :

yarn add vite-node --save-dev

Construisez votre projet

yarn build

Cela entraînera la construction de votre projet avec esbuild et vous verrez un nouveau fichier, dist/index.cjs, qui est la version CommonJS de votre package.

Configurer le point d'entrée

Mettez à jour votre package.json pour qu'il pointe vers votre point d'entrée CommonJS.

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

Bam ! Et voilà, vous avez maintenant construit votre package pour CommonJS. Cela fonctionnera même si vous avez des dépendances ESM car les dépendances seront regroupées
avec votre colis.

Les dépendances sont incluses dans la sortie en raison du champ bundle : true lorsque esbuild est appelé.

Déclarations TypeScript

Bien que techniquement cela ne soit pas requis, vous souhaiterez très probablement également des déclarations TypeScript qu'esbuild ne produit malheureusement pas pour le moment. Donc pour générer
ceux-là, vous voudrez utiliser le tsc normal.

Mettez à jour votre tsconfig.json

L'ajout de ces options à votre fichier tsconfig.json entraînera la sortie uniquement des déclarations TypeScript. C'est exactement ce que nous souhaitons puisque le reste du package
est en cours de construction avec esbuild.

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

Mettez à jour votre script de build

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

Doubles points d'entrée

Ce guide recommande de générer uniquement un seul point d'entrée CommonJS pour votre package. Personnellement, je pense que c'est la meilleure option pour deux raisons :

  • Minimise la taille du paquet
  • Évite le risque de double emballage

Cependant, ce n’est pas la seule option. Vous pouvez également publier votre package avec deux points d'entrée pour CommonJS et ESM.

Mettez à jour votre script de build pour inclure une build ESM

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

Mettez à jour votre fichier package.json pour inclure deux points d'entrée

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

Code source

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn