2020/11版:TypeScript の開発環境を yarn で構築する

9 min読了の目安(約8900字TECH技術記事

今回は開発環境ということで minify や uglify などは行わないところまでとします。
また、 git や npm のローカルの準備は既に終わってるものとします。

TL;DR

yarn init -y
yarn add typescript --dev
yarn run tsc --init
yarn add sirv-cli ttypescript @zoltu/typescript-transformer-append-js-extension rimraf yarn-run-all  --dev

tsconfig.json を設定したら yarn ttsc でトランスパイル完了! 以上!

yarn を初期化して必要なパッケージを入れる

mkdir -p src/ts
mkdir -p public/js
yarn init -y
yarn add typescript --dev
yarn run tsc --init

tsconfig.json を編集する

yarn run tsc --init で tsconfig.json が生成されているので設定を変更していきます。
EcmaScript の各ブラウザ対応状況を確認の上、設定してみました。
デフォルトの "target": "ES3",, "module": "commonjs", でいい気もしますが今回はこうしました。
yarn run tsc --init で生成された tsconfig.json には簡単なコメントもついているのでそれを参考にしながら設定していきましょう。

{
  "compilerOptions": {
    "target": "ES2017",
    "module": "es2015",
    "sourceMap": true,
    "outDir": "./public/js",
    "rootDir": "./src/tsc",
    "removeComments": true,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

テスト実行に必要なファイルを揃える

./public/index.html

<!DOCTYPE html>
<html>
  <head>
    <title>index</title>
    <script type="module" src="./js/index.js"></script>
  </head>
  <body>
    <h1>FooBar</h1>
    <p id="foo"></p>
  </body>
</html>

./src/tsc/index.ts

import { addBaz } from './baz'

window.onload = function () {
  const app = document.getElementById("foo") as HTMLParagraphElement;
  
  app.innerHTML ="Hello Typescript World! foo";
  addBaz(app);
};

./src/tsc/baz.ts

export function addBaz(p:HTMLParagraphElement):void {
  const baz = document.createElement("p");
  baz.textContent = "It is Baz.";

  p?.appendChild(baz);
}

ビルドしてみる

yarn tsc

いい感じですね

確認用の簡易Webサーバーを用意する

HTML+JavaScript をローカルで動作確認するのに
ESModuleを使おうとしたりすると CORS で怒られたりします。
なので確認用の簡易Webサーバーを用意しましょう。
パッケージはいろいろありますが今回は sirv-cli を使います。

yarn add sirv-cli --dev
yarn sirv public --port 8080

import 時の拡張子が必要なのをどうにかする

  • TypeScript での import はコレでイケる
    • import { Foo } from './foo';
  • ブラウザで動かす JavaScript はこうじゃないとダメ
    • import { Foo } from './foo.js';

これがつらたんです。実は TypeScript で import { Foo } from './foo.js'; と書いても
解釈してくれるんですが、 foo.js なんてファイルは ./src/ts/ 配下にはないわけで気持ち悪い。
TypeScript の ISSUE としても上がってるんですが
TypeScript 的には path を書きかえない方針のようなのでどうにかしたいです。

この ISSUE のコメントについてるようなスクリプトを実行してもいいし
いろんな方法がありますね。babel 使うならこれが良さそうです。


今回は ttypescript + @zoltu/typescript-transformer-append-js-extension を使うことにしました。

yarn add ttypescript @zoltu/typescript-transformer-append-js-extension --dev

tsconfing.json にも追記します。最終的にこんな感じですね。

{
  "compilerOptions": {
    "target": "ES2017",
    "module": "es2015",
    "sourceMap": true,
    "outDir": "./public/js",
    "rootDir": "./src/tsc",
    "removeComments": true,
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "plugins": [
      {
        "transform": "@zoltu/typescript-transformer-append-js-extension/output/index.js",
        "after": true,
      }
    ]
  }
}

そしたらビルドしてやりましょう。コマンドが変わります。

yarn ttsc

確認。

index.ts

import { addBaz } from './baz'
// ...後略


index.js

import { addBaz } from "./baz.js";
// ...後略

.js が追記されてますね。オッケー!

トランスパイル前に出力先をきれいにしておく

rimraf を導入してトランスパイル先のディレクトリを削除するようにします。
これで、ファイル名変更などで出力されなくなったファイルなどもちゃんと消えるようになりますね。

yarn add rimraf --dev
yarn rimraf ./public/js/

複数の yarn run を順次/並列に実行する

これまでの作業で

  • トランスパイル前に出力先を全削除
  • トランスパイル実行
  • 開発用サーバーの起動

が揃いました。あとは yarn run する scripts を記述してやるだけなのですが
せっかくなので yarn-run-all (中身は npm-run-all ですがw) を導入して
yarn run を順次/並列実行できるように準備しておきましょう。

yarn add yarn-run-all --dev

yarn run の scripts を書く

こんな感じですね。
今回は yarn-run-all のグロブを使ったスクリプト実行はやりませんでした。

  "scripts": {
    "clean": "rimraf ./public/js/",
    "ttsc": "ttsc",
    "watch": "ttsc --watch",
    "cleanwatch": "run-s clean watch",
    "serve": "sirv public --port 8080",
    "build": "run-s clean ttsc serve",
    "dev": "run-p cleanwatch serve"
  },

最終的な package.json はこんな感じです。

{
  "name": "my_project",
  "version": "1.0.0",
  "main": "index.js",
  "repository": "git@github.com:<userid>/my_project.git",
  "author": "your name",
  "license": "MIT",
  "scripts": {
    "clean": "rimraf ./public/js/",
    "ttsc": "ttsc",
    "watch": "ttsc --watch",
    "cleanwatch": "run-s clean watch",
    "serve": "sirv public --port 8010",
    "build": "run-s clean ttsc serve",
    "dev": "run-p cleanwatch serve"
  },
  "devDependencies": {
    "@zoltu/typescript-transformer-append-js-extension": "^1.0.1",
    "rimraf": "^3.0.2",
    "sirv-cli": "^1.0.8",
    "ttypescript": "^1.5.12",
    "typescript": "^4.0.5",
    "yarn-run-all": "^3.1.1"
  }
}

コマンドはこんな感じです。

# clean して ttsc して sirv でサーバー起動。localhost:8080 で確認できる
# Ctrl+c で停止
yarn build

# clean して ttsc --watch しつつ sirv でサーバー起動。localhost:8080 で確認できる
# Ctrl+c で停止
# TypeScript ファイルを編集して保存すればトランスパイルが走る
# ブラウザで確認しているときは保存後、ハード再読み込みしましょう
yarn dev

以上です。おつかれさまでした。
今回のプロジェクトファイル一式はこちらです。
https://github.com/JUNKI555/yarn_run_practice03

なんで gulp/webpack 使わないの?

yarn でイケたからです

なんで babel 入れてないの?

IE11対応の予定はないし 前述のES2015対応状況などをみるに私の要件には不要と判断したからです

その他の参考サイト