会社の webpack が遅くなってきたので、TypeScript 周りでバンドル速度が改善できるか調べてみました
そして、以下の記述に見つけて、バンドル速度改善をする上で割と重要なオプションな気がしたので実装してみようと思います
GitHub - TypeStrong/ts-loader: TypeScript loader for webpack
今回実装したコードの結果は以下にあげてます github.com
では、簡単ですが実装を説明していきます
実装
ビルドプロセスを並列化する方法として、HappyPackとthread-loaderのどちらかを使う方法があるそうです
ただ、HappyPack の GitHub ドキュメントを見ると、HappyPack はメンテナンスモードに入るそうなので、今回は thread-loader を使うことにします
以下のように他の loader の前に記述することで、以降の loader の処理を並列化します
thread-loader は複数の Worker スレッドで loader を実行することで並列化を実現しています
// webpack.config.js module: { rules: [ { test: /\.tsx?$/, use: [ { loader: 'thread-loader', options: { workers: require('os').cpus().length - 1 } }, 'babel-loader', 'ts-loader', 'tslint-loader', 'stylelint-custom-processor-loader' ], exclude: /node_modules/ } ] }
thread-loader を使う設定ができたら、次は ts-loader の happyPackMode をtrue
にします
happyPackMode をtrue
に設定すると transpileOnly オプションが暗黙的にtrue
になるみたいです
ts-loader は JS へのトランスパイルと静的型チェックを行ってくれるのですが、transpileOnly オプションをtrue
にすると JS へのトランスパイルのみを行います
静的型チェックを行わない場合や他のプラグインで代替する場合は、transpileOnly オプションをtrue
にすることでコンパイル速度を上げることができます
// webpack.config.js module: { rules: [ { test: /\.tsx?$/, use: [ { loader: 'thread-loader', options: { workers: require('os').cpus().length - 1 } }, 'babel-loader', { loader: 'ts-loader', options: { happyPackMode: true } }, 'tslint-loader', 'stylelint-custom-processor-loader' ], exclude: /node_modules/ } ] }
次にFork TS Checker Webpack Pluginを使って型チェックを行います
checkSyntacticErrors オプションをtrue
にしてますが、HappyPack や thread-loader を使用している場合は必須の設定のようです
Fork TS Checker Webpack Plugin は Syntax エラーと Semantic エラーの両方をチェックする機能を備えているのですが、checkSyntacticErrors オプションはデフォルトはfalse
なので Semantic エラーのみをチェックします
しかし、transpileOnly オプションがtrue
でも Syntax エラーはチェックするので、checkSyntacticErrors オプションをtrue
にする必要は本来は無いのですが、happyPackMode をtrue
にした場合は、Syntax エラーはチェックされないみたいなので、checkSyntacticErrors オプションをtrue
にする必要があります
分かりづらいですね、、しかも今回やろうとしてる速度改善とはあまり関係がありません
でもとりあえず設定しておいた方が良さそうです
ちなみにこのことは以下の checkSyntacticErrors の説明の所に書いてました
GitHub - Realytics/fork-ts-checker-webpack-plugin: Webpack plugin that runs typescript type checker on a separate process.
翻訳間違ってたらすみません
// webpack.config.js const ForkTsChecker = require('fork-ts-checker-webpack-plugin') module: { rules: [ { test: /\.tsx?$/, use: [ { loader: 'thread-loader', options: { workers: require('os').cpus().length - 1 } }, 'babel-loader', { loader: 'ts-loader', options: { happyPackMode: true } }, 'tslint-loader', 'stylelint-custom-processor-loader' ], exclude: /node_modules/ } ] }, plugins: [ new ForkTsChecker({ checkSyntacticErrors: true }) ]
実装は以上です
検証
とりあえず実行
約 15 秒
あまり速くなってない。。
試しに thread-loader の Worker の数を 1 つにして実行
こっちの方が倍速いじゃないか!
thread-loader の Worker の数を 2 つにして実行
Worker の数を増やす度に遅くなってる。。😇
原因として今回検証に利用したReact Boilerplateはかなり小規模な検証環境だったので Worker の起動やプロセス間通信にかかるオーバーヘッドの方が大きかったのかなと思います
会社のプロジェクトであれば、そちらはかなり肥大化しているので、今度試してみます