grunt-typescript の watch オプションでさらに速く

この内容は grunt-typescript 0.3.4 (typescript 1.0.0) をもとに記述しています。

ちょっとまえに grunt-typescript 0.3.2 を公開して、「TypeScriptのコンパイルは遅いけど、それでもgrunt-typescriptが最速じゃないだろうか?」ってのを書いたんやけど、思うところあってちょっと触ったらさらに早くなった。バージョンが 0.3.2 から 0.3.4 と 0.3.3 が飛んでるのは、デバック用の console 出力が残っていたっていうご愛嬌。

で、なにをしたかっていうと、コンパイルを実際に実行する TypeScriptCompiler ってのが中にあってそいつのインスタンスを毎回生成してたんやけど、それを使いまわすようにした。で、 TypeScriptCompiler には addFile っていうコンパイル対象になるファイルを追加するメソッドがあるんやけど、ちょっと調べたら updateFile ってのと getDocument ってメソッドがあったので、コンパイル実行前に getDocument メソッドすでにファイルが保持されているか調べて、保持されててかつ変更されたファイルやったら updateFile メソッドを使うように変更した。ファイルが保持されてなかったらもちろん addFile メソッドで追加。さらに内部ではファイルそれぞれに対して Document ってクラスのインスタンスが生成されて管理されてるんやけど、そこらへんのもろもろの処理が updateFile ですっ飛ばされる模様。

で、どうなったかは以下。

$ grunt typescript:watch
Running "typescript:watch" (typescript) task

Watching directory.... c:\Work\Git\typescript\src\compiler
>> Changed c:/Work/Git/typescript/src/compiler/tsc.ts
117 files created. js: 117 files, map: 0 files, declaration: 0 files (14493ms)

Watching directory.... c:\Work\Git\typescript\src\compiler
>> Changed c:/Work/Git/typescript/src/compiler/tsc.ts
1 file created. js: 1 file, map: 0 files, declaration: 0 files (4862ms)

Watching directory.... c:\Work\Git\typescript\src\compiler

前の記事では1回目は14036msだったのが2回目は8761msで約4.5秒ほど速くなっていたのが、今回は約10秒速くなってます。いい感じ。

updateFile は最後の引数に TextChangeRange クラスを渡せるようになってて、多分、変更された部分だけを指定できるようにもなってるようやけど、さすがに diff とかとるほうが遅いと思われる(というかそのコードを書くほうがしんどい)ので、却下。エディタでのライブコンパイルとかやったら使えそうです。

前後に動かすタスクも指定できるよ!

ちなみに watch オプションは、コンパイル前後に動かすタスクも指定できるようになってるんで、今まで grunt-contrib-watch などで一連の処理を流していたものも再現できるのいい感じです。

typescript: {
  base: {
    src: ['path/to/typescript/files/**/*.ts'],
    options: {
      watch: {
        before: ['beforetasks'],   //Set before tasks. eg: clean task
        after: ['aftertasks']      //Set after tasks.  eg: minify task
      }
    }
  }
}