k-tokitoh

トランスパイラがわからない

2024-12-29

仕事では platform 領域の人におまかせしてしまっているし、個人でコードを書くときには雰囲気で設定しているので全然わからなかったが、1 ミリ理解したのでメモする。

色々間違っているかもしれない。

トランスパイラの役割

  • ts -> js の変換
  • 構文の変換

各種ツール

前提

ややこしい理由のひとつは、歴史的経緯によりそれぞれのツールの責務がオーバーラップしていること。

責務の分布について、こちらの記事が 2023-11 時点の見取り図としてわかりやすい。

一気に捉えようとすると混乱するので、トランスパイラについてのみ扱う。

トランスパイラであるライブラリ

いずれも tsconfig.json を設定ファイルとして利用する。

トランスパイル用のライブラリはパフォーマンス観点で選定し、型チェックは本家の tsc で行うのが主流。

  • tsc

    • 型チェックとトランスパイル / 型チェックのみ(noEmit: true) が可能
  • (webpack +) ts-loader

  • (webpack + babel-loader +) @babel/preset-typescript

    • トランスパイルのみが可能
  • swc

    • トランスパイルのみが可能
    • Rust 製
  • esbuild

    • トランスパイルのみが可能
    • Go 製

トランスパイラを利用するライブラリ

next.js

  • swc
  • vercel 帝国の一部

vite

angular

tsconfig の lib, target

あるコードが「この環境では動くがこの環境では動かない」という事象には 2 種類の理由がある。

構文と標準ライブラリである。

例として es2022 の各 feature は以下のように分類される。

  • 構文
    • top level wait
    • private class field
    • private class method
    • static class fields
    • class static initialization blocks
  • 標準ライブラリ
    • Array.at
    • Object.hasOwn
    • Error.cause
    • RegExp ‘d’ flag

書かれたコードをより広範な環境で実行できるようにするためにトランスパイラが何をしてくれる/くれないか。

  • 構文
    • 入力は、トランスパイラのそのパージョンで扱える全ての構文を扱える(設定は関係ない)
    • 出力は、target で指定した水準までダウンレベルされる
  • 標準ライブラリ
    • 入力は、lib で指定したものを扱える
    • 出力は、特に変化しない(lib で指定してもトランスパイラが提供するのは型だけであり実装ではない)
    • そのため、その lib がない環境で動かすためには polyfill が必要となる

lib, target, サポート下限は以下の画像に示すトレードオフの中で定めていく。

polyfill / ponyfill

本筋とはズレるがついでに。

ある機能が一定以上のバージョンでのみ対応されているとき、そのバージョン以下の環境で利用可能にするための 2 つのアプローチ。

  • polyfill
    • 当該 API に対してパッチを当てる
    • ex. Array.prototype にパッチを当てて Array.includes() を拡張する
  • ponyfill
    • 同等の機能を、パッチではなく別途用意する
    • ex. arrayIncludes()という関数を定義する