/타입스크립트-활용/타입스크립트로-ESM,-CJS-모두-지원하는-라이브러리-만들기/thumbnail.png

타입스크립트로 ESM, CJS 모두 지원하는 라이브러리 만들기

TL;DR

타입스크립트의 설정 파일 tsconfig.json을 활용하면 ECMAScript(ESM)과 CommonJS(CJS)에 모두 대응되는 라이브러리를 개발할 수 있습니다.
이 문서는 복수 개의 tsconfig.json 파일을 설정하여 ECMAScript(ESM)과 CommonJS(CJS)에 모두 대응되는 라이브러리를 빌드할 수 있도록 설정하는 방법을 소개합니다.

안내사항

이 문서를 이해하기 위해서는 문서의 내용 이외에 아래의 배경 지식이 필요합니다.

  1. 타입스크립트 설정 파일 tsconfig.json의 구조
  2. 타입스크립트 설정 파일의 module, extends, outDir 필드
  3. 자바스크립트의 문법 형식 CommonJS(CJS), ECMAScript(ESM)에 대한 개념

소개

타입스크립트 개발자는 타입스크립트 설정 파일인 tsconfig.json을 통해 타입스크립트 코드를 어떤 버전의 문법으로 작성할지, 어떤 버전의 문법으로 빌드될지를 포함하여 다양한 설정을 진행할 수 있습니다.

이 문서는 moduleoutDir 필드를 통해 CommonJS(CJS) 및 ECMAScript(ESM) 문법의 다중 빌드 환경 구성 방법을 다룹니다.
원활한 빌드 설정을 위해 tsconfig.base.json 기본 설정 파일을 구성한 후, tsconfig.esm.json, tsconfg.cjs.json을 통해 ESM, CJS 문법에서 tsconfig.base.json 설정을 상속하여 사용하도록 구성하였습니다.

⚠️ 본 문서는 빌드 이후 내보내기 과정에 대해 다루고 있지 않습니다 [참조 포함됨]

본 문서는 타입스크립트를 통해 ESM 및 CJS로 빌드하는 방법을 다루고 있지만, 타입스크립트 빌드 이후 라이브러리 외부로 타입 힌트 및 라이브러리 코드를 내보내는 방법에 대해서 다루고 있지 않습니다.
라이브러리 외부로 타입 힌트, 라이브러리 코드를 내보내기 위한 조건부 내보내기을 공부하기 위해서는 JavaScript/TypeScript 모두 지원하는 라이브러리 만들기 (with Conditional Exports) 문서를 참고해주세요.

배경 지식

배경지식 1: 타입스크립트 설정 중 extends 필드를 사용하면 다른 설정 파일의 내용을 계승/상속할 수 있습니다.

json
// 예시: tsconfig.base.json 파일 상속하기
{
"extends": "./tsconfig.base.json" // tsconfig.base.json 설정을 상속합니다
}

배경지식 2: extends 필드 아래에 원하는 설정을 입력하면 계승 대상의 설정에 원하는 내용을 덮어씌울 수 있습니다.

json
// 예시: tsconfig.base.json 설정 상속하여 CommonJS로 빌드 후 dist/cjs 경로로 빌드 결과 저장하도록 설정하기
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
// 원하는 compilerOptions을 덮어 씌울 수 있습니다
"module": "CommonJS",
"outDir": "dist/cjs"
}
}

배경지식 3: module 필드를 통해 타입스크립트가 특정한 형식으로 빌드되도록 설정할 수 있습니다.

json
// 예시: tsconfig.base.json 설정 상속하여 ESM으로 빌드 후 dist/esm 경로로 빌드 결과 저장하도록 설정하기
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "ES2020", // 타입스크립트 코드를 ES2020 버전에 맞게 빌드합니다
"outDir": "dist/esm"
}
}

배경지식 4: outDir 필드를 통해 빌드 완료된 코드를 어디에 저장할 지 지정할 수 있습니다.

json
// 예시: tsconfig.base.json 설정 상속하여 ESM으로 빌드 후 dist/esm 경로로 빌드 결과 저장하도록 설정하기
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "ES2020",
"outDir": "dist/esm" // 빌드 후 결과물을 dist/esm으로 저장합니다
}
}

타입스크립트 설정하기: ESM, CJS 개별 빌드 설정 파일 만들기

이제 프로젝트 디렉토리에 기본 설정 파일 tsconfig.base.json과 ESM 빌드 설정 파일 tsconfig.esm.json, CJS 빌드 설정 파일 tsconfig.cjs.json을 설정해야 합니다.

설정 시작 전 확인해주세요:

  1. 기본 설정 파일 tsconfig.base.json은 각자의 프로젝트에 맞게 설정해주세요.
  2. 필요한 타입스크립트 설정 정보 extends, module, outDir에 대해서는 배경지식에서 다루고 있습니다.
  3. 이미 작성된 예시가 궁금하다면 @devcomfort/text-transcoder 레포지토리의 tsconfig.base.json, tsconfig.esm.json, tsconfig.cjs.json 파일을 참조할 수 있습니다.

아래는 각각 ESM, CJS 문법에 맞게 빌드하기 위한 설정 파일입니다.

tsconfig.esm.json

json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "ES2020",
"outDir": "dist/esm"
}
}

tsconfig.cjs.json

json
{
"extends": "./tsconfig.base.json",
"compilerOptions": {
"module": "CommonJS",
"outDir": "dist/cjs"
}
}

빌드 테스트하기: ESM, CJS 각각 빌드해보기

tsconfig.esm.json, tsconfig.cjs.json 설정 후 아래와 같이 빌드 명령을 사용하면 각각 문법 버전에 맞게 빌드할 수 있습니다.

bash
# CommonJS(CJS) 빌드 명령 (각각 npm, yarn, pnpm에서)
npm tsc --project tsconfig.cjs.json
yarn tsc --project tsconfig.cjs.json
pnpm tsc --project tsconfig.cjs.json
bash
# ECMAScript(ESM) 빌드 명령 (각각 npm, yarn, pnpm에서)
npm tsc --project tsconfig.esm.json
yarn tsc --project tsconfig.esm.json
pnpm tsc --project tsconfig.esm.json

package.json scripts 설정하기: ESM, CJS 동시에 빌드되도록 설정하기

@devcomfort/text-transcoder에는 다음과 같이 package.jsonscripts 필드를 설정하여 build 명령을 통해 ESM, CJS 동시 빌드가 가능하도록 설정하였습니다.

package.json

bash
{
...
"scripts": {
"build:cjs": "tsc --project tsconfig.cjs.json",
"build:esm": "tsc --project tsconfig.esm.json",
"build": "pnpm build:cjs && pnpm build:esm",
...
}
...
}

scripts 필드를 위 코드처럼 설정하면 build 명령을 통해 build:cjs, build:esm을 순차적으로 실행하여 CommonJS(CJS) 버전과 ECMAScript(ESM) 버전 코드를 모두 빌드할 수 있습니다.

참조

프로젝트 내용은 v0.2 기준 @devcomfort/text-transcoder 프로젝트 업데이트에서 다룬 내용입니다. 실제 프로젝트에서 사용된 tsconfig.base.json, tsconfig.cjs.json, tsconfig.esm.json 또한 프로젝트 레포지토리 내에 있으므로 궁금하신 분은 참고 바랍니다.