体感!JavaScriptで超速アプリケーション開発 -Meteor完全解説

第2回Meteorアプリケーションの実行環境

Meteorの実行環境

連載第2回では、Meteorアプリケーションの実行環境についてお話しします。

Meteorは、すべてをJavaScriptで書くことができるという利点を最大限に活かし、サーバとクライアントでコードを共有したり、サーバのコードをクライアントから呼び出すことができます。そうしたことを実現するには、今回の内容を理解しておく必要がありますが、幸いにも大して難しい話ではありません。

MeteorによるJavaScript/CSSの管理自動化

HTML/JavaScriptを用いたクライアントを作成する上で、いつも頭を悩ませるのがリソースの管理です。

大規模なアプリケーションともなると、JavaScriptやCSSが数十ファイルに上ることも珍しくありません。それらを通常の<script>や<link>で読み込むと、それらのファイルを読みこむごとにHTTPリクエストが発生するため、ページの読み込み速度に深刻な影響を与えます。なので、本番運用時には、それらのファイルをミニファイ(空白やコメントなどを除去するなどして、ファイルサイズを最小化すること)した上で結合し、リクエスト回数とダウンロードサイズを最小化することが望まれます。

ですが、結合とミニファイを行なってしまうと、ソースコードの可読性が著しく損なわれるため、Webブラウザ上でのデバッグはほぼ不可能になってしまいます。

なので、開発時に限っては、個々のファイルはやはり別々に読み込みたいところです。

そのため、⁠開発時は各ファイルを個別に読み込む」⁠本番運用時はファイルをミニファイ・結合する」といったリソース管理が望まれます。ですが、それを実現するには、読み込み元となるHTMLファイルのソースコードを、開発時と本番時で変更しなければならないため、管理が面倒です。

Meteorは、こうしたリソース管理をすべて自動化してくれます。このことを、Meteorのサンプルで確認してみましょう。

meteor create --example wordplayと実行すると、Meteorに付属するサンプルがひな形として生成されます。生成されたコードを見ると、複数のサブディレクトリ内にJavaScriptファイルが分散しています。

図1 wordplayサンプルのプロジェクトディレクトリ
図1 wordplayサンプルのプロジェクトディレクトリ

生成されたディレクトリに移動して、meteorコマンドを実行すると、3000番ポートでの実行が行われます。Webブラウザで http://localhost:3000 にアクセスしてみましょう。図2のような実行結果を得られるはずです。

図2 wordplayサンプルの実行結果
図2 wordplayサンプルの実行結果

このサンプルは、ランダムに並んだアルファベットを組み合わせて作れる単語を見つけ出すゲームです。Webブラウザ上でページのソースコードを表示してみると、以下のように、恐ろしいほどの数のJavaScriptファイルが読みこまれていることがわかります。

図3 ローカル環境でのHTMLソースコード
図3 ローカル環境でのHTMLソースコード

今度はこれを、Meteorが用意するテスト環境にデプロイして、同じようにコードを見てみましょう。プロジェクトのディレクトリでmeteor deploy <任意のID>.meteor.comを実行し、指定したドメインにアクセスすると、ローカルと同じ実行結果を得られるはずです。ここでページのソースを表示してみると、ローカルで実行した結果とは全く異なっています。

図4 本番環境でのHTMLソースコード
図4 本番環境でのHTMLソースコード

あれだけあった<script>が、たったひとつの<script>要素に置き換わっています。この<script>によって読み込まれているファイルを見てみると、きちんとミニファイも施されており、ファイルサイズも最小限に抑えられていることがわかります。

さらに、結合されたJavaScriptのファイルは、ファイル内容から生成されたハッシュ値が名前に付けられており、長いキャッシュ期間を割り当てられています。ファイルの内容が変化したら自動的にファイル名も変更されるため、キャッシュが更新されずに頭を悩ますこともありません。

特に設定などを施さずとも、これだけリソース管理を自動化してくれるというのは、驚異的といっても過言ではないでしょう。前回の記事でも触れたとおり、Meteorはとことん開発を楽にする点に重点を置かれているというのがおわかりいただけるのではないでしょうか。

以降は、Meteorにおけるリソース管理のルールを説明していきたいと思います。

Meteorアプリケーションのディレクトリ構造

Meteorプロジェクトは単一の親ディレクトリをルートとして、複数のHTML/JavaScript/CSSファイルやサブディレクトリから構成されています(ちなみに、プロジェクトのディレクトリ内には.meteorという隠しディレクトリが生成されています⁠⁠。

プロジェクトのサブディレクトリのうちでも、以下の名称を持つものは、Meteorにとって特別な扱いのもとで管理されます。

client
クライアント側で実行されるJavaScriptファイルやCSSファイル、HTMLファイルを格納する
server
サーバ側で実行されるJavaScriptを格納する
public
静的なファイル(画像など)を格納する。このディレクトリ内のファイルはMeteorによって特別な処理を行われることなく、⁠そのまま」静的ファイルとして配信されます。

また、これら以外の場所(プロジェクトディレクトリ直下や、上記以外のサブディレクトリ)にも、JavaScriptやCSS、HTMLを置くことができます。この中でもJavaScriptファイルについては、⁠サーバでもクライアントでも実行される」というのが重要です。この仕組みのおかげで、サーバとクライアントで共通のコードを利用することも容易です。

ここで述べたルールを、次はファイルの種類という切り口から説明しなおしてみます。

HTMLファイルの扱い

HTMLファイルは、serverディレクトリ以外の場所に置くこともできます。serverディレクトリに置くこともできますが、置いても意味はありません。

HTMLファイルはかなり特殊な取り扱いを受けるので注意が必要です。serverpublicディレクトリ以外に置かれたHTMLファイルは、Meteorによってその内容をすべてスキャンされ、1つのHTMLファイルにまとめられます。具体的には、<head>、<body>、<template>(この要素については、次回以降に説明します)の内容を抜き出され、1つに結合されます。

このことが意味するのは、Meteorアプリケーションは基本的に1つのHTMLファイルから構成されるということです。開発の都合に応じてHTMLを分割することはできますが、それらは実行時に結合されます。このように、Meteorが動的にHTMLを生成するという動作をするおかげで、本番時のみJavaScriptをミニファイ・結合するという動作が可能になるわけです。

また、Meteorが行う自動的なファイル結合の結合順序ですが、ファイルの結合はディレクトリごとに行われます。ディレクトリはアルファベット順でソートされたあと、深さ優先で探索され、個々のディレクトリにおけるファイル結合は、ファイル名のアルファベット順で行われるようです。これは、以降のCSSファイル、JavaScriptファイルにも同じことが言えます。

HTMLファイルの取り扱いについて、具体的なサンプルとともに見てみましょう。以下のサンプルは、プロジェクトのさまさまな位置にHTMLファイルを置いて、実行結果を見てみるものです。

サンプルは以下からダウンロードできます。

図5 サンプル1-1のディレクトリ構造
図5 サンプル1-1のディレクトリ構造

個々のHTMLファイルは、以下の様な単純なものです。ルートディレクトリからのパスを、ページ内容として記述しています。

<body>
  <section>
    <h1>a/a.html</h1>
  </section>
</body>

実行結果は図6のようになります。深さ優先a/a.htmlよりもa/b/b.htmlが先に来ている⁠⁠、アルファベット順client/part1.htmlpart2.htmlよりも先に来ている)で結合されていることがおわかりでしょう。

図6 サンプル1-1の実行結果
図6 サンプル1-1の実行結果

また、publicディレクトリ以下のHTMLファイルpublic.htmlは、実行結果に表れていません。public以下のファイルは静的なファイルとして、ファイル結合やミニファイの対象にはなりません。

CSSファイルの扱い

CSSファイルは、serverディレクトリ以外の場所に置くことができます。プロジェクト内にあるCSSファイルは自動的にHTMLの<link>要素で読み込むコードが生成されますpublicディレクトリ内のファイルは除く⁠⁠。本番環境では、serverpublicディレクトリ以外に置かれたCSSファイルが結合・ミニファイされます。

JavaScriptファイルの扱い

JavaScriptファイルは、あらゆるディレクトリに置くことができます。サーバ側で実行されるJavaScriptはserverディレクトリに、クライアント側で実行されるJavaScriptはclientディレクトリに、静的に配信したいJavaScriptファイルはpublicディレクトリに配備します。それ以外の場所においたJavaScriptファイルは、サーバでもクライアントでも実行されます。

server、public以外の場所に置かれた、クライアント側で実行されるJSファイルは、本番環境においてはすべて結合・ミニファイされます。

JavaScriptファイルをMeteorがどう取り扱うかについて、サンプルでの動作を確認してみましょう。

サンプルは以下からダウンロードできます。

サンプル1-2は、図7のようなファイル構成になっています。

図7 サンプル1-2のディレクトリ構造
図7 サンプル1-2のディレクトリ構造

JavaScriptファイルに注目してみると、以下のようになります。

common.js
サーバ上でもクライアント上でも実行される
client/index.js
クライアント(Webブラウザ)上でのみ実行される
server/server.js
サーバ上でのみ実行される

ソースコードを以下に示します。

common.jsには、以下のような関数が定義されています。console.log()メソッドを使って、文字を出力するだけの関数です。

function hello() {
    console.log("Hello");
}

以下に示すのが、サーバ側で実行されるserver.jsのソースコードです。common.jsで定義されているhello()メソッドを使用しています。ここで使用しているMeteor.startup()は、Meteorが初期化された際に一度だけ呼び出されるメソッドです。

Meteor.startup(function () {
    hello();
});

次はクライアント側を見てみましょう。まずはHTMLコードです。ボタンがひとつ配置されているだけの、単純な画面です。

<head>
  <meta charset="UTF-8">
  <title>サンプル1-2</title>
</head>
<body>
  <h1>サンプル1-2</h1>
  <button id="button">クリック!</button>
</body>

最後に、クライアント側で実行されるclient.jsのソースコードです。ここでも、common.jsで定義されているhello()が使用されていることに注意してください。

window.onload = function() {
    var button = document.getElementById('button');
    // ボタンが押されたらhello()を呼ぶ
    button.addEventListener('click', function() {
        hello();
    }, false);
};

このサンプルを実行すると、まずサーバ側のコンソールに"hello"という文字列が表示されます。

図8 サーバ起動時のコンソール
図8 サーバ起動時のコンソール

http://localhost:3000 にアクセスすると、図9のような画面が表示され、ボタンをクリックするとブラウザのコンソールに"hello"という文字列が表示されます。

図9 クライアントでの実行結果
図9 クライアントでの実行結果

まとめ

今回は、Meteorプロジェクトのファイル構成について詳しく説明しました。Meteorを使用すると、サーバとクライアントで簡単にコードを共有できるだけではなく、JavaScript/CSSのコードをミニファイ・結合するというフローも自動化されます。

非常に強力な仕組みですが、プロジェクト内のHTMLコードがすべて1つにまとめられるという動作は、よく理解する必要があるでしょう。

おすすめ記事

記事・ニュース一覧