TypeScript 프로젝트 참조가 필요하지 않을 수도 있습니다

Jared Palmer
Name
Jared Palmer
X
@jaredpalmer

대규모 TypeScript 코드베이스나 모노레포에서 작업한 적이 있다면 프로젝트 참조에 익숙할 것입니다. 실제로 매우 강력합니다.

tsconfig.json에서 프로젝트를 참조하면 새로운 일이 발생합니다:

멋지게 들리죠! 그렇죠?! 음...어쩌면요. 프로젝트에 참조를 추가하면 이제 패키지를 추가하거나 제거할 때마다 계속 업데이트해야 합니다. 좀 귀찮네요.

음...필요하지 않다면 어떨까요?

"내부" TypeScript 패키지

제가 "내부 패키지"라고 부르는 패턴을 사용하면 참조나 중간 TypeScript 빌드 단계조차 필요하지 않을 수 있습니다.

"내부 패키지"는 tsconfig.json이 없는 TypeScript 패키지로, package.jsontypesmain 필드 모두 패키지의 트랜스파일되지 않은 진입점(예: ./src/index.tsx)을 가리킵니다.

package.json
{
  "name": "@sample/my-internal-package"
  "main": "./src/index.ts"
  "types": "./src/index.ts", // yes, this works!
  "dependencies": {
    ...
  },
  "devDependencies": {
    ...
  }
}

TypeScript 언어 서버(VSCode에서)와 타입 체커는 원시 .ts 또는 .tsx 파일을 자체 유효한 타입 선언으로 처리할 수 있습니다. 이 마지막 문장은 두 번 읽으면 명백합니다. 그러나 명백하지 않은 것은 types 필드를 원시 소스 코드에 직접 가리킬 수 있다는 것입니다.

이렇게 하면 2가지 규칙을 준수하는 한 이 패키지를 프로젝트 참조나 TypeScript 빌드 단계(tsc 또는 esbuild 등을 통해) 없이 사용할 수 있습니다:

제가 알기로는 이 내부 패키지 패턴은 Turborepo를 사용하든 다른 도구를 사용하든 관계없이 모든 yarn/npm/pnpm 워크스페이스 구현에서 작동합니다. 여러 다른 메타 프레임워크(아래 참조)로 이 패턴을 개인적으로 테스트했지만 다른 프레임워크에서도 작동할 것으로 확신합니다.

Next.js

Next.js 13은 로컬 패키지(모노레포와 같은) 또는 외부 종속성(node_modules)의 종속성을 자동으로 트랜스파일하고 번들링할 수 있습니다.

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  transpilePackages: ['@acme/ui', 'lodash-es'],
};
 
module.exports = nextConfig;

Next.js 13.1부터 next-transpile-modules 패키지가 더 이상 필요하지 않습니다. 자세한 내용은 Next.js 내장 모듈 트랜스파일레이션 블로그 게시물을 참조하세요.

Vite

내부 패키지가 그냥 작동합니다. 추가 구성이 필요하지 않습니다.

React Native

Expo를 사용하고 expo-yarn-workspaces 또는 @turborepo/adapter-expo 패키지를 사용하는 경우 iOS 또는 Android를 타겟팅하는 한 내부 패키지를 사용할 수 있습니다. 이러한 플랫폼에서 Expo를 실행하면 모든 node_modulesMetro로 자동으로 트랜스파일됩니다. 그러나 웹용 Expo를 타겟팅하는 경우 node_modules가 웹용으로 트랜스파일되지 않기 때문에 내부 패키지가 작동하지 않습니다.

Expo 팀에 이 불일치에 대해 연락했습니다. 그들은 이를 인지하고 있습니다. 레거시 문제라고 들었습니다.

이 패턴의 아름다움

이 패턴은 불필요하거나 중복된 빌드 단계를 절약하기 때문에 훌륭합니다. 또한 구성 없이 프로젝트 참조의 모든 편집기 이점을 제공합니다.

주의사항

내부 패키지를 사용하면 소비 애플리케이션에 또 다른 소스 디렉토리가 있다고 말하는 것과 같습니다. 장단점이 있습니다. 소비 애플리케이션이 커지면 더 많은 내부 패키지를 추가하는 것은 해당 소비 애플리케이션에 더 많은 소스 코드를 추가하는 것과 동일합니다. 따라서 더 많은 소스 코드를 추가하면 트랜스파일/번들/타입 체크할 코드가 더 많아지므로 소비 애플리케이션의 빌드가 느려질 수 있지만(수행할 작업이 더 많기 때문) 전체 빌드 시간은 잠재적으로 더 빠르고 덜 복잡할 수 있습니다. 전체 빌드 시간이 저하되기 시작하면 더 큰 내부 패키지를 .d.ts 파일과 일반 TypeScript 빌드 단계가 있는 "일반" 패키지로 다시 변환하기로 결정할 수 있습니다.

앞서 언급했듯이 이 패턴은 실제로 Turborepo와 거의 관련이 없습니다. 그냥 매우 훌륭하고 여러분이 알고 있어야 한다고 생각합니다. Turborepo용 프리셋 패키지 빌드 규칙(즉, "빌더")을 적극적으로 작업하고 있기 때문에 내부 패키지 패턴을 사용하여 빌드 단계를 건너뛸 것입니다.

긴 빌드 시간에 대해 말하자면...

부끄럽지만 홍보를 하겠습니다. 이 게시물을 읽고 있고 느린 빌드 및 테스트 시간으로 어려움을 겪고 있다면 Turborepo가 어떻게 도움이 될 수 있는지 보여드리고 싶습니다. Turborepo가 모노레포의 빌드 시간을 50% 이상 단축할 것을 보장합니다. 여기에서 라이브 데모를 요청할 수 있습니다.