May 01, 2023
typescript의 모듈추론방식에 대해 의문이 생겨 정리해보고자 함
타입스크립트를 사용할 때, import를 한다는 것은 개발을 위해 모듈을 불러옴도 맞지만 타입스크립트 자체로서는 import 해오는 모듈이 어떤 타입인지를 알기위함도 있다고 함 (런타임혹은 번들링때가 아님)
타입스크립트가 import해오는 모듈에 대한 타입을 추적하기 위해 아래와 같은 전략들을 씀
참고로, baseurl이 작성된 (이후의 Path 정의 포함) 얘들은 비상대경로로 치는듯 함
classic은 제외하였음
아마 가장 많이사용되고있었던 방식. Node 11 이하의 버전의 commonJs의 모듈방식만을 사용하던 노드 기반에서 유용
일반적으로 대부분의 번들러와 호환이 잘 됨
Module 필드또한 동일한 값 매칭 됨
여기서부터 commonJS뿐 아니라, ESM(es 모듈방식)이 지원됨 CJS, ESM의 가능성을 모두 열어놓은 값이기 때문에, 두가지 모두 호환 가능한 방식으로 개발이 되어야 함(엄격함)
Package.json의 exports 필드를 이해할 수 있게 됨
아래 경로에 대한 변경점들은 Pakcage.json type또한 모듈로 프로젝트 내부의 파일들이 ESM모듈로더를 사용할 경우인것 같음(혹은 esm기준의 파일?)
Import 할 때 컴파일되는 파일의 확장자가 필수로 입력되어야 함. ts가 아닌 최종컴파일되어 반환되는 파일의 확장자가 작성되어야 함. 즉, .js
맞긴 함.. 컴파일할 때 안바꿔줌 path도.. 그래서 bundler에 함께 명시해주어서 따로 꼭 잡아줘야 하긴 하지. 깡 node 프로젝트를 할 때, 패키지 타입이 module로 esm모듈로더를 사용한다고 하면 확장자를 입력해주는게 필수이기도 하고…
??/index.js 라는 디렉토리를 찾을수 없는것이겠지..?
package.json의 exports필드를 이해할 수 있게 되면서, 그 필드 기준으로 내보내진것들만 찾을 수 있음.
‘bundler’ for use with bundlers. Like node16 and nodenext, this mode supports package.json “imports” and “exports”, but unlike the Node.js resolution modes, bundler never requires file extensions on relative paths in imports.
위 설명 그대로 아래가 문제없이 잘 잡힘
얘는 아무것도 컴파일 안해줌(타입스크립트 -> 자바스크립트는 당연히 해주고) 우리가 사용하는 번들에게 모든것을 위임하여 완화된 값임. 그래서 vite cli에서는 Bundler를 사용하고있음
어떠한 도구의 도움 없이(번들러 등등) 순수 ESM은 깡 node 환경에서 구성을 해도 import 경로에 확장자가 필수로 입력되어야 하지만 CJS는 아님
package.json type = CJS, moduleResolution=nodeNext
로 tracing 했을 때 dynamic import 대한 resolve 기준만 Esm임. 나머지 정적import는 모두 CJS기준으로 나옴.package.json type = module(ESM), moduleResolution=nodeNext
로 돌리면, 정적임포트던 dynamic import던 모두 esm으로 나옴. 그래서 resolving 할 때 ESM 기준으로 돌기 때문에, 온전히 찾기 위해 확장자가필수적으로 작성되어야 했던 것.moduleResolution=Node
로 tracing하면 패키지 타입이 CJS던 ESM이던 저 Resolving 기준이 없음. 당연히 moduleResolve기준이 CJS로 돌려서인것 같고, CJS는 확장자 필요 없으니 문제 x이사람들은 타입스크립트만을 사용한다는 기준으로 개발을 했을것임(모듈로더 관련 확장자 등등에 대한 어떤 툴의 도움도 고려 x로 esm 기반의 프로젝트에서도 node환경에서 잘 돌아가야 했음)
파일의 확장자에 모듈로더방식이 명시되어있는게 아니면 moduleResolution nodeNext(현재 node16동일)부터 package.json의 type을 보고 각 모듈들이 어떠한 방식으로 import 하는 모듈들을 찾을 지 결정한다 함.
This tells TypeScript that you want your imports and exports to conform strictly to the Node spec.
해당속성은, 타입스크립트에게 들이기, 내보내기 규칙에 온전히 Node 기준을 따르라는 명시
이전과는 다르게 앞으로는 확장자 그것도 컴파일 이후의 Js 확장자를 써줘야 함이 개발자들사이에서 낯설다(?)라는 의문을 많이 남긴듯 함.
esm이 지원됨으로 변경되면서 esm 모듈로더 기반 패키지에서는 확장자가 필요한 상황이 되었는데 아마 타입스크립트 자체만으로서는 다른 번들러와 같은 툴들의 도움을 온전히 배제하고 본인만으로 모두 가능해야하기때문에, 낯설긴 하지만 이게 올바른 방향이라고 생각되긴 함..
그래서 5버전에 bundler라는 값이 나왔고, 위와같이 엄격한 검사를 더이상 타입스크립트가 하지 않고 번들러에게 넘긴다는 개념.