Node.js 모듈시스템과 CJS, ESM

Node.js 모듈 시스템이란?

모듈: 분리된 파일 각각, 클래스 하나 혹은 라이브러리 하나

필요한 모듈을 불러오고 내보낼 때의 모듈을 구성하는 방법이다.

Node.js에서는 CJS, ESM 두 가지가 존재한다.

CJS, ESM의 특징과 호환성

모듈 결정

아래 방식이 대표적이고 자세한 부분은 공식문서에서도 확인할 수 있다.(공식문서)

  • 확장자

    • cjs(ts v4.7부터 cts): CJS

    • mjs(ts v4.7부터 mts): ESM

  • package.json의 type 필드

    • type = commonjs: CJS

    • type = module: ESM

CommonJS (CJS)

  • require / module.exports

  • module loader가 동기적으로 동작

ECMAScript Modules (ESM)

  • import / export

  • module loader가 Top-level Await 지원으로 비동기적으로 동작

ESM과 CJS 함께 지원

  1. 진입점(cjs/index.js, esm/index.js) 파일 구성

  2. 각 모듈 방식에 따라 컴파일

// CJS
$ npx tsc --module CommonJS --outDir cjs/

// ESM
$ npx tsc --module es2022 --outDir esm/
  1. package.json의 exports 필드를 통해 모듈별 패키지 entry point 지정

파일 시스템 상의 위치와 import path를 다르게 가져갈 수 있다.

{
  "exports": {
    ".": {
      "require": "cjs/index.js",
      "import": "esm/index.js"
    }
  }
}

트러블 슈팅

  • Typescript 지원

CJS

{
  "exports": {
    ".": {
      "require": {
        "types": "./index.d.ts",
        "default": "./index.js"
      },
      "import": {
        "types": "./index.d.mts",
        "default": "./index.mjs"
      }
    }
  }
}

ESM

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

  • 경로는 상대 경로로 작성

{
  "exports": {
    ".": {
      "require": {
        "types": "dist/index.d.ts", (x)
        "types": "./index.d.ts", (o)
      },
      ...
    }
  }
}

References

Last updated