공부공부/TS

[typescript 핸드북] 10. 모듈 해석

고생쨩 2024. 2. 19. 09:33
728x90

typescript 핸드북 학습내용 정리
https://typescript-kr.github.io/pages/the-handbook.html

모듈 해석

모듈 해석 (module resolution)은 컴파일러가 import가 무엇을 참조하는지 알아내기 위해 사용되는 프로세스.

  • 첫번째로 모듈을 나타내는 파일의 위치를 찾고 못 찾으면 ambient 모듈을 찾으려고 함. 못 찾으면 오류

상대적 vs 비상대적 모듈 import

상대적 - 경로 지정됨

가져온 파일에 상대적으로 해석되고 ambient 모듈 선언으로 해석 될 수 없음

import Entry from "./components/Entry";
import { DefaultHeaders } from "../constants/http";
import "/mod";

비상대적 - 나머지 전부

baseUrl로 해석되거나, 밑에서 다루게 될 경로 매핑으로 해석될 수 있습니다. ambient 모듈 선언으로도 해석될 수 있음.
외부 의존성을 import할때 비상대적 경로를 사용해

import * as $ from "jquery";
import { Component } from "@angular/core";

모듈 해석 전략

클래식

TS의 디폴트 해석 전략으로 사용됨. 주로 이전 버전과의 호환성을 위해 제공됨

상대적 import

import하는 파일에 상대적으로 해석됨.
소스 파일 /root/src/folder/A.ts안에 import { b } from “./moduleB”`인 경우

/root/src/folder/moduleB.ts  
/root/src/folder/moduleB.d.ts  

위 경로를 찾음.

비상대적 import

소스 파일 /root/src/folder/A.ts안에 import { b } from "moduleB"인 경우

/root/src/folder/moduleB.ts
/root/src/folder/moduleB.d.ts
/root/src/moduleB.ts
/root/src/moduleB.d.ts
/root/moduleB.ts
/root/moduleB.d.ts
/moduleB.ts
/moduleB.d.ts

위 경로를 찾음

노드

node.js가 모듈을 해석하는 방법

require 함수를 호출해 수행함.

상대경로

var x = require(“./moduleB”);라는 import 문을 포함한 /root/src/moduleA.js의 경우

  1. /root/src/moduleB.js라는 파일이 존재하는지 확인.
  2. 만약 “main” 모듈을 지정하는 package.json라는 파일을 포함하고 있으면, /root/src/moduleB 폴더 확인하기. 이 예제에서는, 만약 Node.js가 { “main”: “lib/mainModule.js” }을 포함하는 /root/src/moduleB/package.json파일을 찾았다면, Node.js가 /root/src/moduleB/lib/mainModule.js를 참조
  3. index.js 라는 파일을 포함하고 있으면, /root/src/moduleB 확인

비상대적 경로

한줄 요약 node_modules에서 찾음

TS가 모듈을 해석하는 방법

ts는 node.js의 런타임 해석전략을 모방함. (ts, tsx, d.ts 등 확장자만 늘어남)

추가 모듈 해석 플래그

  • 컴파일 후 소스 파일의 경로와 이름이 일치 하지 않을 수 있음.
  • TS 컴파일러는 예상되는 변환을 컴파일러에게 알리기 위한 추가 플래그 세트가 있음

기본 URL

baseUrl을 설정하는 것은 컴파일러에게 어디에서 모듈을 찾을지 알려주는 것

  • baseUrl 명령 줄 인수 값 (만약 주어진 경로가 상대적이면, 현재 디렉터리를 기준으로 계산됨)
  • 'tsconfig.json’안에 baseUrl 프로퍼티 값 (만약 주어진 경로가 상대적이면, 'tsconfig.json’의 위치를 기준으로 계산됨)

경로 매핑

모듈이 baseUrl 내에 없을때 tsconfig.json에 path 설정

{
  "compilerOptions": {
    "baseUrl": ".", // "paths"가 있는 경우 반드시 지정되어야함.
    "paths": {
      "jquery": ["node_modules/jquery/dist/jquery"] // 이 매핑은 "baseUrl"에 상대적임.
    }
  }
}

여러개의 위치도 매핑이 가능함.

projectRoot
├── folder1
│   ├── file1.ts (imports 'folder1/file2' and 'folder2/file3')
│   └── file2.ts
├── generated
│   ├── folder1
│   └── folder2
│       └── file3.ts
└── tsconfig.json

위 경우 tsconfig.json

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "*": [
        "*",
        "generated/*"
      ]
    }
  }
}

rootDir 가상디렉토리

rootDirs을 사용하면, 컴파일러에게 이 가상 디렉토리를 구성하는 roots를 알릴 수 있음.

 src
 └── views
     └── view1.ts (imports './template1')
     └── view2.ts

 generated
 └── templates
         └── views
             └── template1.ts (imports './view2')
{
  "compilerOptions": {
    "rootDirs": [
      "src/views",
      "generated/templates/views"
    ]
  }
}

./#{locale}/messages와 같은 상대 모듈 경로의 일부로 #{locale}와 같은 특수 경로 토큰을 보간하여 빌드 툴이 로케일 전용 번들을 자동으로 생성하는 국제화 시나리오

// ./zh/messages
export default [
    "您好吗",
    "很高兴认识你"
];
// tsconfig.json
{
  "compilerOptions": {
    "rootDirs": [
      "src/zh",
      "src/de",
      "src/#{locale}"
    ]
  }
}

'./#{locale}/messages’를 './zh/messages’로 해석

모듈 해석 추적

–traceResolution 를 사용하여 모듈 해적 추적이 가능함

│   tsconfig.json
├───node_modules
│   └───typescript
│       └───lib
│               typescript.d.ts
└───src
        app.ts
tsc --traceResolution //컴파일러 호출

출력

======== Resolving module 'typescript' from 'src/app.ts'. ========
Module resolution kind is not specified, using 'NodeJs'.
Loading module 'typescript' from 'node_modules' folder.
File 'src/node_modules/typescript.ts' does not exist.
File 'src/node_modules/typescript.tsx' does not exist.
File 'src/node_modules/typescript.d.ts' does not exist.
File 'src/node_modules/typescript/package.json' does not exist.
File 'node_modules/typescript.ts' does not exist.
File 'node_modules/typescript.tsx' does not exist.
File 'node_modules/typescript.d.ts' does not exist.
Found 'package.json' at 'node_modules/typescript/package.json'.
'package.json' has 'types' field './lib/typescript.d.ts' that references 'node_modules/typescript/lib/typescript.d.ts'.
File 'node_modules/typescript/lib/typescript.d.ts' exist - use it as a module resolution result.
======== Module name 'typescript' was successfully resolved to 'node_modules/typescript/lib/typescript.d.ts'. ========

import의 이름과 위치

  • ======== ‘src/app.ts’ 에서 ‘typescript’ 모듈 해석. ========

컴파일러가 따르는 전략

  • 모듈 해석 종류가 지정되지 않으면, 'NodeJs 사용.

npm 패키지에서 types 로딩

  • 'package.json’은 'node_modules/typescript/lib/typescript.d.ts’를 참조하는 ‘types’ 필드 './lib/typescript.d.ts’가 있습니다.

최종 결과

  • ======== 모듈 이름 'typescript’는 'node_modules/typescript/lib/typescript.d.ts’로 성공적으로 해석 되었습니다. ========

–noResolve 사용하기

명령줄에 추가하지 않은 파일은 컴파일에 추가하지 않도록 지시함

import * as A from "moduleA" // 성공, 'moduleA'가 명령줄로 전달됨
import * as B from "moduleB" // Error TS2307: Cannot find module 'moduleB.
tsc app.ts moduleA.ts --noResolve

제외 목록에 있는 모듈을 컴파일러가 선택하는 이유

  • tsconfig.json은 폴더를 "프로젝트"로 바꿈.
  • 제외하고 싶으면 tsconfig.json에서 exclude를 사용
  • 포함하고 싶으면 tsconfig.json에서 files 사용

이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.