Vue.js が templateURL をサポートしない理由

Oct 28, 2015

もともと Angular を使っていて、Vue に移行した新規ユーザから頻繁に寄せられる質問のひとつに「templateURL はありますか?」というものがあります。これについてはかなりの回数お答えしてきましたが、このことについて記事を書いた方が良いとわかりました。

Angular では、templateURL または ng-include を使うことで、外部のテンプレートファイルを実行時に動的ロードすることができます。これらは、組み込み機能としてはとても便利に思えます。しかしこれが解決する問題とは一体何なのか、再考してみましょう。

最初の1つは、分割した HTML ファイル内にテンプレートを書くと、エディタ内で正しいシンタックスハイライトが付くことです。だからこそ、 HTML ファイルを分割することが好む人がたくさんいるのでしょう。しかし JavaScript コードとテンプレートを分割するのは本当に最善の方法でしょうか? Vue.js のコンポーネントでは、テンプレートと JavaScript はもともと密接に関連付けられています - 実際のところ、同じファイル内に存在したほうがよりシンプルです。2ファイル間を行ったり来たりするコンテキストの切り替えは、開発体験を悪化させてしまいます。概念的には、コンポーネントとは Vue.js アプリを構成する基本的なブロックであり、テンプレートではありません。すべての Vue.js テンプレートは JavaScript のコンテキストと関連付けられています - それらをさらに引き裂いても意味がありません。

次に、ファイルを分割して開発する場合、結合するためのビルド手順が必要ですが、templateURL を使うと実行時に Ajax 経由でテンプレートを読み込むので、この手順は不要になります。これは開発中は便利ですが、本番環境にデプロイする時には深刻な代償を払うことになります。HTTP/2 が普遍的にサポートされるまでは、アプリケーションの初期ロードパフォーマンスにとって、HTTP リクエストの数は最も重大な要素であり続けるでしょう。あなたのアプリ内のすべてのコンポーネントで templateURL を使うことを想像してください - ブラウザは何を表示するのにも何ダースもの HTTP リクエストを実行する必要があります!ご存知かもしれませんが、ほとんどのブラウザは1つのサーバに実行できる並列リクエスト数を制限しています。この制限を超過すると、あなたのアプリの初期レンダリングはブラウザが待機状態になる余計なラウンドトリップに悩まされることになるでしょう。もちろん、ビルドツールを用いて $templateCache 内にそれらのテンプレートを事前登録することでこれに対処することはできます - しかしそのことは、どのようなフロントエンド開発においても、現実的にはビルド手順は必要不可欠である、ということを示しています。

では、templateURL なしでどのように開発体験の問題に取り組むべきでしょうか?テンプレートをインラインJavaScript文字列として書くのはひどいものですし、<script type="x/template"> を使ってテンプレートを偽装するのはハックのように感じます。では、このゲームから降りて、WebpackBrowserify のような適切なモジュールバンドラを使う頃合いかもしれませんね。これらを使ったことがなければ、ひるんでしまうかもしれませんが、飛び込む価値はあると保証します。巨大でメンテナンス可能なものを作りたいのであれば、適切なモジュール化が必要です。さらに大事なことは、Vue の単一ファイルコンポーネントを使うと、適切なシンタックスハイライトと、カスタムプリプロセッサ、ホットリローディング、デフォルトで ES2015 準拠、自動プレフィックス付加や scoped CSS による利便性を得られますし、それによって開発体験は10倍はよくなるということです。

最後に、Vue を使うことでコンポーネントの遅延ローディングが可能になりますし、Webpack を使うことでより簡単にこれを行うことができます。ただ、初期バンドルが巨大になるので分割したほうがいいかもしれません。

テンプレートではなく、コンポーネントで考えましょう。