Hatena::ブログ(Diary)

IT-Walker on hatena このページをアンテナに追加 RSSフィード

2012-04-13

1分でWebアプリを作れて、3分で公開できた!オールJavaScriptでWebアプリを開発できるMeteorを触ってみた


もうJavaもRubyも要らない?–JavaScriptオンリーの未来派WebアプリフレームワークMeteorがデビューという記事で知った、新しいフレームワークMeteor。

ちょっと気になったので、軽く触ってみました。すごすぎるフレームワークの登場です!!

正確に言うと、実行環境&フレームワーククラウドPaaS&パッケージマネージャーといったところでしょうか。Node.jsとHerokuとnpmが一緒になったようなもんだと思えば、イメージがわくと思いますが、実態はそれらを上回っています(パッケージ数はnpmの比じゃありませんが・・・使い勝手という意味で)。

インストール

ターミナルをたちあげて、以下のコマンドを実行するだけ。

(行頭の$はターミナルであることを表してるだけで、コマンドの一部じゃありません)

$ curl install.meteor.com | sh

これで /usr/local/bin/meteor コマンドがインストールされます。

Meteorを実行する

meteorコマンドを使うと、簡単にプロジェクトを作って実行できます。

# leaderboardというサンプルを作成
$ meteor create --example leaderboard
# 生成されたディレクトリに移動
$ cd leaderboard
# meteorコマンドを実行
$ meteor

meteorコマンドは、3000番ポートでリクエストを待ち受けます。

なので、http://localhost:3000にアクセスすると、早速サンプルを実行できます。

f:id:Syunpei:20120413083301p:image

人名をクリックして、ボタンを押すとなんか5ポイント与えることができるという、意味なしアプリではありますが、とりあえず実行できました!ここまでの所要時間はだいたい1分くらいでしょうか・・。

公開する

meteorで作ったアプリ、すぐさまクラウド上で公開することもできます。

公開するためのコマンドは meteor deploy です。

$ meteor deploy firstapp

deployのあとに与える引数はサイトのIDみたいなもので、自由につけることができます。ここでつけたIDがドメイン名に含められ、公開されたアプリにアクセスするには「http://<id>.meteor.com」にアクセスします。

上のコマンドではIDを「firstapp」としていますので、以下のURLでアクセスすることができます。

http://firstapp.meteor.com/


しかし、ユーザ登録すらしてないんですけど!!なんでそんなんでアプリ公開できちゃうの!?

で、このままだと世界中の誰もが同じIDでアプリアップロードしあえたりしちゃいそう。知らない人同士がアプリを上書きしあったりするとカオスですね。


その対処のためだと思うのですが、アップロード時にパスワードを設定することもできます。パスワードを設定するには、「meteor deploy --password <id>」とするだけ。初回はパスワードを聞かれます。一度パスワードを設定したら、同じパスワードを入力しないとアップロードができなくなります。

$ meteor deploy firstapp --password
New Password: *****
Confirm Password: *****
Deploying to firstapp.meteor.com.  Bundling ... uploading ... done.
Now serving at firstapp.meteor.com

meteorコマンド一覧

meteorで使用できるコマンドは以下のとおり。

コマンド説明
run[デフォルト] プロジェクトをローカルの開発環境で動かします
create新しいプロジェクトを作成します
updateMeteorを最新バージョンにアップデートします
addプロジェクトにパッケージを追加します
removeプロジェクトからパッケージを取り除きます
list利用可能なパッケージをリスト表示します
bundleプロジェクトをtarballに固めます
mongo特定のサイトのMongo DBに接続します
deployMeteorにプロジェクトをデプロイします
logs指定されたサイトのログを表示します
resetプロジェクトの状態をリセットし、ローカルのデータベースを削除します

LESSもCoffeeScriptも使えます

コマンドの概要がわかったところで、meteor list してみた結果が以下。CoffeeScriptもLESSもunderscoreも使えます。

  • amplify - Cross browser API for Persistant Storage, PubSub and Request.
  • autopublish - Automatically publish all data in the database to every client
  • backbone - A minimalist client-side MVC framework
  • code-prettify - Syntax highlighting of code, from Google
  • coffeescript - Javascript dialect with fewer braces and semicolons
  • handlebars - Simple semantic templating language
  • htmljs - Easy macros for generating DOM elements in Javascript
  • jquery - Manipulate the DOM using CSS selectors
  • jquery-history - pushState module from the jQuery project
  • jquery-layout - Easily create arbitrary multicolumn layouts
  • jquery-waypoints - Execute a function when the user scrolls past an element
  • less - The dynamic stylesheet language.
  • showdown - Markdown-to-HTML processor
  • underscore - Collection of small helper functions (map, each, bind, ...)

コードはどうなっている?

作成されたプロジェクトのコードを見てみると、なかなか興味深いことがわかります。

まず、HTML/JS/CSSのコードが1ファイルずつ、計3ファイルできているのみです。非常に見通しが良い。

その他気づいたこととしては、以下の様なものが挙げられます。

以下に、生成されたコードにコメントを付与したものを掲載します。まずleaderboard.htmlから。

<!-- html要素やDOCTYPEは書かなくていい。Meteorが勝手に追加する -->
<head>
  <title>Leaderboard</title>
</head>

<body>
  <div id="outer">
    <!-- leaderboardテンプレートの内容を出力する -->
    {{> leaderboard}}
  </div>
</body>
<!-- テンプレート。結果のHTMLには含まれない -->
<template name="leaderboard">
  <div class="leaderboard">
    <!-- プレイヤーをループしながら、playerテンプレートの内容を出力する。
      この「players」という変数への参照が、JavaScriptコードの呼び出しを伴う(後述)
    -->
    {{#each players}}
      {{> player}}
    {{/each}}
  </div>

  <!-- プレイヤーが選択されていれば、以下のHTMLを出力
    この「selected_name」という変数への参照が、JavaScriptコードの呼び出しを伴う(後述)
  -->
  {{#if selected_name}}
  <div class="details">
    <div class="name">{{selected_name}}</div>
    <input type="button" class="inc" value="Give 5 points" />
  </div>
  {{/if}}

  <!-- 選択されていない場合 -->
  {{#unless selected_name}}
  <div class="none">Click a player to select</div>
  {{/unless}}
</template>

<!-- テンプレート:player -->
<template name="player">
  <!-- この「selected」という変数への参照が、JavaScriptコードの呼び出しを伴う(後述) -->
  <div class="player {{selected}}">
    <span class="name">{{name}}</span>
    <span class="score">{{score}}</span>
  </div>
</template>

次はJavaScriptファイル(leaderboard.js)。MeteorのAPI全開ですが、理解に困ることはありません。

たったこれだけのコードで、MongoDBを使った永続化まで行えています!!

// プレイヤーの情報を含むコレクション。
// サーバサイドでは、"players"という名前でMongoDBに保存される
Players = new Meteor.Collection("players");

// クライアントで実行されている場合
if (Meteor.is_client) {
  // テンプレート中で「players」を参照しているコードが、このメソッドを呼び出す
  Template.leaderboard.players = function () {
    // プレイヤーをすべて出力する。スコアの降順、かつ名前の昇順
    return Players.find({}, {sort: {score: -1, name: 1}});
  };
  // テンプレート中で「selected_name」を参照しているコードが、このメソッドを呼び出す
  Template.leaderboard.selected_name = function () {
    // セッションに格納されているIDをキーとしてプレイヤーを一件取得
    var player = Players.findOne(Session.get("selected_player"));
    return player && player.name;
  };

  // テンプレート中で「selected」を参照しているコードが、このメソッドを呼び出す
  Template.player.selected = function () {
    return Session.equals("selected_player", this._id) ? "selected" : '';
  };
  // leaderboardテンプレート内で発生したイベントの処理
  Template.leaderboard.events = {
    // incクラスが付与されたinput要素がクリックされたら
    'click input.inc': function () {
      // プレイヤーデータをアップデート
      Players.update(Session.get("selected_player"), {$inc: {score: 5}});
    }
  };
  // playerテンプレート内で発生したイベントの処理
  Template.player.events = {
    // クリックされたら、IDをセッションに格納する。
    'click': function () {
      Session.set("selected_player", this._id);
    }
  };
}
// サーバ上で実行されている場合
if (Meteor.is_server) {
  // サーバが開始される際、データベースが空の場合はデータを格納する
  Meteor.startup(function () {
    if (Players.find().count() === 0) {
      var names = ["Ada Lovelace",
                   "Grace Hopper",
                   "Marie Curie",
                   "Carl Friedrich Gauss",
                   "Nikola Tesla",
                   "Claude Shannon"];
      for (var i = 0; i < names.length; i++)
        Players.insert({name: names[i], score: Math.floor(Math.random()*10)*5});
    }
  });
}

そして、これらのコードが実行されると、結果のHTMLコードにテンプレートは含まれず、すべてJSによるDOM操作でUIが構築されます。

さらに、デプロイされた本番環境においては、JSが自動的にミニファイ&結合(すごい!!)されるので、生成されるHTMLがこんなにシンプルになっちゃいます。

<!-- Meteorによって自動生成されたHTMLコード -->
<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="/908bc3c56d644ff869b6e756fb9374343d414b09.css">
  <title>Leaderboard</title>
  <script type="text/javascript" src="/9de2e7b06f1251b8acc06fb6517643959c540b29.js"></script>
</head>
<body>
</body>
</html>

まとめ

Meteor、すごいです!あっという間にアプリを作れて、生成されたコードの見通しはいいし、PaaSまでついていて、おまけに本番環境でのJSミニファイ&結合機能付き!!

これまで、手作業でセットアップしていた多くの事柄が完全に自動化されています。


Webアプリ作成も、ついにここまで簡単になったか・・・という感じです。

プログラマ失業を本気で心配しなくちゃならなくなって来ました・・

celladorsaikoucelladorsaikou 2013/05/11 02:01 なるほど

参考になりました

他の記事も拝見させていただきます

ありがとうございます

はてなユーザーのみコメントできます。はてなへログインもしくは新規登録をおこなってください。