ESM vs CJS (commonjs)

자바스크립트 세부사항 스터디

Posted by jopemachine on October 7, 2021 Updated on September 27, 2022

ESM vs commonjs

Common Javascript (CJS)

  • CJS는 동기적으로 모듈을 import 하는 require 구문을 사용한다.

  • CJS는 top level await 구문 때문에 ESM 모듈을 require 할 수 없다.

  • CJS에서 ESM 모듈을 사용하려면 dynamic import 구문을 사용해 mjs 파일에 직접 접근해 사용해야 한다.

ESM

  • ES6에서 도입된 새로운 스타일의 ESM Script.

  • ESMCJS와 많은 부분에서 다르게 작동하기 때문에 (this가 global object를 참조하지 않고 use strict가 기본 값이고 json을 import 해 올 수 없고 등등…) 여전히 CJS가 노드의 디폴트로 사용된다.

  • CJS와 다르게 모듈 로더를 비동기 환경에서 실행한다. 스크립트를 병렬적으로 다운로드, 로드 하는 것이고 실행은 정의된 순서대로 실행된다.

  • deno의 경우 ESM을 디폴트로 사용한다.

  • Node 12.17.0 이후 부터 experimental 플래그 없이도 사용 가능하게 되었다.

  • mjs 확장자를 사용하거나 type: "module"를 사용

  • require를 만들어 CJS를 사용할 수 있다. 다만 default import의 케이스에만 가능한 점에 유의해야 한다. (Tree shaking이 불가능함) CJS named exports를 제공해야 한다면 ESM Wrapper로 감싸서 제공할 수 있다.

CJS vs ESM

  • CJSESM을 dual로 구성하는 방법도 있다. 하지만 해당 패키지의 다른 두 버전이 함께 로드되었을 때 충돌 가능성이 있고 일반적으로 사용하기엔 무리가 있는 방법이다.

  • 좋은 Dual package를 만드는 방법은 CJS 스크립트를 만들고 ESM wrapper로 CJS named exports를 감싼 후, package.jsonexports를 추가하는 것이다.