"Si un ouvrier veut bien faire son travail, il doit d'abord affûter ses outils." - Confucius, "Les Entretiens de Confucius. Lu Linggong"
Page de garde > La programmation > Création de packages NPM pour CommonJS avec des dépendances ESM

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

Publié le 2024-08-14
Parcourir:301

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

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 l'installer :

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 :

  • Réduit la taille du bundle
  • É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 = ""
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()

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

Déclaration de sortie Cet article est reproduit sur : https://dev.to/ryan_pate_f494c0931176673/how-to-build-npm-packages-for-commonjs-with-pure-esm-dependencies-38jm?1 En cas d'infraction, veuillez contacter Study_golang. @163.com supprimer
Dernier tutoriel Plus>

Clause de non-responsabilité: Toutes les ressources fournies proviennent en partie d'Internet. En cas de violation de vos droits d'auteur ou d'autres droits et intérêts, veuillez expliquer les raisons détaillées et fournir une preuve du droit d'auteur ou des droits et intérêts, puis l'envoyer à l'adresse e-mail : [email protected]. Nous nous en occuperons pour vous dans les plus brefs délais.

Copyright© 2022 湘ICP备2022001581号-3