All Articles

타입스크립트의 project reference 맛보기

언제 쓰나?

타입스크립트를 이용해서 모노리포를 구성하다보면 의존하고 있는 모듈들을 어떻게 빌드할까가 문제가 된다.

각 모듈의 package.json의 main, type 필드를 트랜스파일되지 않은 타입스크립트 파일로 지정하고 일단 개발을 하고, 트랜스파일된 결과를 실제 js로 돌릴 때는 별도로 모듈매핑을 해주는 방법도 있지만 일단 이 글에서는 각 패키지를 js로 빌드한 후 일반적인 node.js 모듈처럼 import해서 사용하는 경우를 다룬다.

yarn workspace 아래에 @shik/a, @shik/b, @shik/c 3개 프로젝트가 있고 (이하 a, b, c), a 프로젝트가 b, c 프로젝트를 불러와서 사용하는 경우를 가정해보자 리포 링크. a 프로젝트를 트랜스파일 하려면 b, c 프로젝트를 빌드해야 하는데 이걸 yarn workspaces run tsc 이런 식으로 동시에 돌릴 수도 없고 (의존하는 패키지 빌드가 먼저 끝나야 다음 패키지 빌드를 할 수가 있다)…결국 빌드 스크립트가 지저분해지기 마련이다.

타입스크립트의 Project reference라는 기능은 이런 문제를 해결해준다. a 프로젝트의 tsconfig.jsonreferences 필드에 의존하는 다른 패키지 (b,c)를 적어주고, 그 패키지의 tsconfig.json에서 composite 옵션을 켜주면 이제 tsc로 a를 빌드하면 알아서 의존 관계에 따라 먼저 b,c를 트랜스파일하고 a를 트랜스파일 해준다. 다음 번에 빌드를 하더라도 새로 빌드가 필요한 부분만 다시 빌드해줘서 불필요하게 모든 프로젝트가 다시 빌드되지 않게 해준다.

처음 빌드 할 때

의존하는 프로젝트를 찾아서 순서대로 트랜스파일 해준다.

$ git clone git@github.com:zxzl/tasting-typescript-project-reference.git && cd tasting-typescript-project-reference
$ yarn
$ yarn workspace @shik/a tsc -b -v
[10:50:45 PM] Projects in this build:
    * ../b/tsconfig.json
    * ../c/tsconfig.json
    * tsconfig.json

[10:50:45 PM] Project '../b/tsconfig.json' is out of date because output file '../b/dist/src/index.js' does not exist

[10:50:45 PM] Building project 'somedirectory/packages/b/tsconfig.json'...

[10:50:46 PM] Project '../c/tsconfig.json' is out of date because output file '../c/dist/src/index.js' does not exist

[10:50:46 PM] Building project 'somedirectory/packages/c/tsconfig.json'...

[10:50:46 PM] Project 'tsconfig.json' is out of date because output file 'dist/src/index.js' does not exist

[10:50:46 PM] Building project 'somedirectory/packages/a/tsconfig.json'...

파일이 바뀔 때

여기서 만약 b를 수정한다면..? b, a만 다시 트랜스파일되고 c는 트랜스파일 되지 않는다.

// packages/b/src/index.ts
export const add = (a: number, b: number) => a + b; // old

export const add = (a: number, b: number, c?: number) => a + b; //new
$ yarn workspace @shik/a tsc -b -v
[10:52:31 PM] Projects in this build:
    * ../b/tsconfig.json
    * ../c/tsconfig.json
    * tsconfig.json

[10:52:31 PM] Project '../b/tsconfig.json' is out of date because oldest output '../b/dist/src/index.js' is older than newest input '../b/src/index.ts'

[10:52:31 PM] Building project 'somedirectory/packages/b/tsconfig.json'...

[10:52:31 PM] Project '../c/tsconfig.json' is up to date because newest input '../c/src/index.ts' is older than oldest output '../c/dist/src/index.js'

[10:52:31 PM] Project 'tsconfig.json' is out of date because oldest output 'dist/src/index.js' is older than newest input '../b'

[10:52:31 PM] Building project 'somedirectory/packages/a/tsconfig.json'...

참조한 글들

Published 17 Jun 2020

If I keep marking the dots, someday they will 🔗🔗
Hyeungshik Jung on Twitter