"일꾼이 일을 잘하려면 먼저 도구를 갈고 닦아야 한다." - 공자, 『논어』.
첫 장 > 프로그램 작성 > ESM 종속성을 사용하여 CommonJS용 NPM 패키지 빌드

ESM 종속성을 사용하여 CommonJS용 NPM 패키지 빌드

2024-08-14에 게시됨
검색:743

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인 종속성이 있다는 사실을 처리하는 데 특히 어려움을 겪었습니다. 나는 번들러에 익숙하지 않고(주로 웹앱 백엔드에서 작업했습니다) 주제에 대한 좋은 가이드를 찾을 수 없었기 때문에 이 문제를 처리하기가 매우 어렵다는 것을 알았습니다.

따라서 다른 사람이 이 문제를 겪고 있다면 해결책은 다음과 같습니다.

가이드

에스빌드 설치

우리는 번들러에 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가 호출되면 true입니다.

TypeScript 선언

기술적으로는 필요하지 않지만 불행히도 현재 esbuild가 출력하지 않는 TypeScript 선언도 필요할 것입니다. 그래서
를 생성하려면 그렇다면 일반 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-dependent-38jm?1에서 복제됩니다.1 침해가 있는 경우, Study_golang에 문의하세요. @163.com 삭제
최신 튜토리얼 더>

부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.

Copyright© 2022 湘ICP备2022001581号-3