13. ES Module, Dynamic Import, Top Level await
13-1. ES Module
CommonJS
문법이 표준 문법이라고 생각할 수도 있는데, 사실 표준은 아니다.
자바스크립트 자체에 표준이 없었기 때문에, CommonJS
라는 자체적인 표준을 정해서 쓰고 있었던 것이다.
그런데 ES Module
이 표준으로 정해지면서 ES Module
문법을 많이 사용하고 있다.
아직 100% ES Module
만을 사용하기엔 한계가 있지만, 장기적으로 봤을 때, CommonJS
에서 ES Module
로 대체가될 것이다.
확장자는 mjs
를 쓴다.CommonJS
는 확장자를 cjs
를 쓸 수 있다.
그런데 그렇게 안하는 이유는 js
확장자로해도 cjs
가 디폴트이기 때문이다.
CommonJS
의 require
, module.exports
, exports
이런건 함수 및 객체이다.
사용자가 마음만 먹으면 다른 값으로 변형할 수도 있다.
하지만 ES6 Module
문법은 예약어이다.
사용자가 마음대로 바꿀 수 없다.
13-1-1. package.json type: module
mjs
확장자를 사용하기 싫다면, package.json
에 "type": "module"
을 넣어주자.
그러면 js
파일도 ES Module 파일로 인식을 한다.import
할 때, js
, mjs
이런 확장자는 생략할 수 없다.require
로 할 땐, 생략 가능했다.
13-1-2. 확장자 생략
노드 창시자가 편의상 확장자 및 index.js
이런 파일명 생략을 가능하게 했는데, 창시자가 직접 이렇게 만든걸 후회한다고 했다.
그래서 ES Module
부터는 확장자 및 파일명을 정확히 명시해줘야된다.
13-1-3. __filename, __dirname, import.meta.url
ES 모듈에서는 __filename
, __dirname
, require
, module.exports
, exports
사용 불가능하다.__filename
대신 import.meta.url
, __dirname
은 import.meta.url
에서 추출하면 된다.
CommonJS에서 ES Module 호출 가능하다.
ES Module에서도 CommonJS 호출 가능하다. (안되는 케이스들도 좀 있음)
13-2. Dynamic Import
CommonJS
모듈에서는 다이나믹 임포트가 되는데, ES Module
에서는 다이나믹 임포트가 안된다.
const a = false;
if (a) {
// 다이나믹 임포트는 이렇게 if 문같은거에 넣는걸 말한다.
// 즉, a가 false 이므로 여기는 실행될 일이 없다.
require('./func.mjs');
}
console.log('성공');
const a = false;
if (a) {
// 그런데 이런건 안된다.
// ES Module에선 import는 반드시 최 상단에 위치해야된다.
import './func.mjs';
}
console.log('성공');
그럼 ES Module에서는 다이나믹 임포트가 불가능한가?
그건 또 아니다.
다이나믹 임포트를 위해서 새로운 문법이 준비가 되어있다.
const a = true;
if (a) {
// import는 promise이기 때문에 await를 써줘야된다.
const a1 = await import('./func.mjs');
console.log(a1);
const a2 = await import('./var.mjs');
console.log(a2);
}