LoginSignup
28

More than 5 years have passed since last update.

TypeScript 3.0 の Project reference(プロジェクト参照) やってみた

Last updated at Posted at 2018-07-31

TypeScript 3.0 がリリースされました。

追加機能のひとつ、Project references は、ちょうど仕事で「どうするのがいいの?」と迷ってたところだったので、さっそくやってみました。

話としてはよくある、 複数のプロジェクトから参照される "共通プロジェクト" の在り方 です。

Project Reference 適用以前

Project Reference 適用前(つまり現状)は、次のような構成になっていました(説明簡略化のため、client -> shared のみを書いてますが serverside からも shared を参照しています)。

root
├── client
│   ├── tsconfig.json
│   └── src
│       └── main.ts
└── shared
    └── src
        └── calc.ts

shared の calc.ts

export function calcAdd(x: number, y: number): number {
    return x + y;
}

client の main.ts

import { calcAdd } from '../../shared/src/calc';

console.log(calcAdd(1, 2)); // = 3

client の tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "outDir": "./dist",
    "strict": true,
    "esModuleInterop": true
  }
}

shared/ 配下 は ただのファイル置き場 で、client から相対パスで calc.ts を参照しているに過ぎません。

これを tsc -b client/tsconfig.json した結果は次のようになります。

root
├── dist
│   ├── client
│   │   └── src
│   │       └── main.js
│   └── shared
│       └── src
│           └── calc.js
├── client
│    └─-
└── shared
     └─-

これはイケてないと思いつつ開発してきましたが、これを Project reference に変えてみます。

Project reference 適用後

ではプロジェクト参照を使ってみます。TypeScript Version 3.0.1 で試しています。

まず、 shared/ をプロジェクト化するために tsc --inittsconfig.json を作り、内容を次のようにします。

shared の tsconfig.json

{
  "compilerOptions": {
    // tsc --init で既定で設定されてた項目
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,

    // あとから追加した項目
    "outDir": "../dist/shared",
    "rootDir": "./src",
    "composite": true,
    "declaration": true,
  }
}

"composite": true がプロジェクト参照のために必要な項目で、"declaration": true は、型定義ファイルを出力するために必要です(よね?)。outDirrootDir は出力される .js ファイルの場所を調整するために設定しました。

次に client 側の tsconfig.json を修正します。

client の tsconfig.json

{
  "compilerOptions": {
    // tsc --init で既定で設定されてた項目
    "target": "es5",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,

    // あとから追加した項目
    "outDir": "../dist/client",
    "rootDir": "./src",

    // さらに追加した相対パス地獄を防ぐための項目
    "baseUrl": "./",
    "paths": {
      "shared/*": [
        "../dist/shared/*"
      ]
    }
  },
  // あとから追加した項目
  "references": [
    { "path": "../shared" }
  ]
}

こちらには、 "references" を追加し、shared への参照を設定します。これがプロジェクト参照のメインですね。

baseUrlpaths は、 "relative path hell" を回避するための設定です。

を見てやってみました。

最後に、client の main.tsimport 文を書き換えます。

client の main.ts

import { calcAdd } from 'shared/calc';

console.log(calcAdd(1, 2)); // = 3

import は、shared プロジェクトのビルド結果である ./dist/shared を参照するようにしますが、 先に baseUrlpathsshared/*../dist/shared/* をマッピングさせているので、ここでは from 'shared/calc' だけで済みます。

ではビルドしてみましょう。

tsc -b client/tsconfig.json

を実行します。ポイントは、shared もプロジェクトなのにそれは含めていない、ということです。

ビルド結果を含むディレクトリ全体は次のようになります。

root
├── client
│   ├── tsconfig.json
│   └── src
│       └── main.ts
├── shared
│   ├── tsconfig.json
│   └── src
│       └── calc.ts
└── dist
    ├── client
    │   └── main.js
    └── shared
        ├── calc.js
        └── calc.d.ts

なんだかそれっぽくなった気がします。
tsc -b client/tsconfig.json としたのに、プロジェクト参照に設定されている shared 側も(先に)ビルドされて dist/shared に出力されています。

client の tsconfig.json には "rootDir": "./src" を設定したので、好き勝手に別の親ディレクトリにある .ts ファイルを参照することができなくなり、秩序が守られる気がします。

冒頭の説明には、もっとたくさんのオプションについて説明がありますが、とりあえず以上です。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
28