はじめてのExpress.js

Introduce Express

1.expressとは
2.なぜ Node.js + express を使うか
3.Getting started
4.パッケージの追加
5.Express + MongoDB

 
Githubにまとめたものを、せっかくなのでblogの方に転記しました。 一部ブログ用に加筆修正しています。

1.expressとは

expressは、Node.jsの軽量WebアプリケーションフレームワークRubySinatraのようなシンプルなフレームワークです。
Node.jsのHTTPサーバ機能は、プロトコルの仕様にそったローレベルなものであるため、
WebApplicationを開発しようとした場合、HTTPリクエストの解析から行わなければなりません。
(Java ServletやRuby Webrickのようなイメージ)

そのため、WebApplicationFrameWorkが必要となります。

2.なぜ Node.js + express を使うか

Node.js + express で開発するメリットは何か

メリット

  • 開発言語をJavaScriptに統一できる
  • ノンブロッキングI/O

開発言語をJavaScriptに統一できる

WebアプリケーションはJavaScriptの開発が欠かせなくなっており、 Java + JavaScriptRuby + JavaScriptといったスキルセットが 当たり前に求められるようになってきました。Node.js + express で開発をするとフロントからバックエンドまで、すべて言語をJavaScriptで統一できます。

ノンブロッキングI/O

Node.jsはGoogle Chromのv8エンジンで処理を行っており、 JavaScriptのイベント・ループをベースに非同期処理を行っています。

  • DB問い合わせで同期処理待ちを行わない
  • WebSocketのコネクションで待機処理を行わない

このような特徴から、シングルスレッドでも沢山のリクエストをさばくことが出来ます。

3.Getting started

早速インストールからサーバの起動までやってみます。

1) Install

$ npm install -g express
$ which express

2) Generate

$ express helloWorld

expressコマンドを実行してnpm installで依存パッケージをインストールします。
expressによって生成されるモジュールは以下のようなものです。

$ cd helloWorld
$ npm install
$ tree -C  -I node_modules
 .
 ├── app.js
 ├── package.json
 ├── public
 │   ├── images
 │   ├── javascripts
 │   └── stylesheets
 │       └── style.css
 ├── routes
 │   ├── index.js
 │   └── user.js
 └── views
     ├── index.jade
     └── layout.jade

viewは名前の通りのビューを、routesはコントローラとモデルを定義していきます。 なお、モデルとコントローラを分けたい場合は、自分でmodelディレクトリを切って分けることも可能です。モデルを分けたら、routesのファイル内でrequireしてあげれば利用できます。

生成されたapp.jsが処理の中心になっています。
依存関係のモジュールや環境設定、ルーティングなどを定義します。

app.jsの内容

f:id:taise:20130627221214p:plain

3) Hello World

Nodeサーバー起動

$ node app

http://localhost:3000/にアクセスすると、indexページが表示される。
expressの処理の流れは以下の図のようになっています。

f:id:taise:20130627221805p:plain

せっかくなので、上の図の処理の流れを見ながら画面表示する内容を変えてみます。

トップページに、コントローラから渡された"Hello World"と表示するには routes/index.jsを以下のように変更します。

exports.index = function(req, res){
  res.render('index', { title: 'Express' });
};

    ↓

exports.index = function(req, res){
  res.render('index', { title: 'Hello Wold' });
};

Nodeサーバー起動

$ node app

http://localhost:3000/にアクセスすると、タイトルが変更されています。

4.パッケージの追加

さてここまできたら、せっかくなので簡単なユーザ登録アプリを作ってみます。
ユーザ登録をすると一覧表示されるようなものです。

こんな感じ。

f:id:taise:20130627222833p:plain

まずはデータの保存/参照機能を追加します。
今回はDBにMongoDBを使用します。
Node.jsにはMongoDBのODM(Object Document Mapper)のmongooseというライブラリがあります。

Node.jsは、npmとpackage.jsonを使ってパッケージ管理をしているので、以下のようにmongooseを追加します。

1) package.jsonにmongooseを追加する

{
  "name": "helloWorld",
    "version": "0.0.1",
    "private": true,
    "scripts": {
      "start": "node app.js"
    },
    "dependencies": {
      "express": "3.2.6",
      "jade": "*",
      "mongoose": ">= 1.0.0"
    }
}

2) npm install

$ npm install

3) requireして利用する

追加したパッケージを利用するには、利用するファイル内でrequireをします。

var db = require('mongoose')

5.Express + MongoDB

1) DBコネクト

mongooseを追加したので、MongoDBと連携させます。
まずは、routes/user.jsでDBコネクトします。

var db = require('mongoose');
db.connect('mongodb://localhost/helloWorld');

2) スキーマ定義

routes/user.jsにschemaを追記します。

var schema = new db.Schema({
  id    : { type: String }
 ,name  : { type: String }
 ,age   : { type: Number }
});

3) Model定義

スキーマで定義したオブジェクトをModelとして登録します。

var User = db.model('User', schema);

4) createリクエストの作成

Userデータを作成する画面を追加します。
まずはapp.jsにルーティングを追加します。 usersでpostされたら、routse/user.jsのcreateに渡します。

app.post('/users', user.create);

次にroutes/user.jsにcreate処理を書いていきます。 createは、mongooseのModel.createを使ってデータを保存します。

exports.create = function(req, res){
  User.create({
    id   : req.param('id')
   ,name : req.param('name')
   ,age  : req.param('age')
  }, function(err) {
    res.send('created')
  });
};

次に、画面を作成します。
既にあるviews/index.jadeをコピーして作ります。

$ cp views/index.jade views/user.jade

コピーしたら中身を以下のように書き換えます。

extends layout

block content
  h1 Add User
    form(action='/users', method='post')
      input(type='text', name="id", placeholder="id")
      br
      input(type='text', name="name", placeholder="name")
      br
      input(type='text', name="age", placeholder="age")
      br
      input(type='submit', value='登録')

画面が作成できたので、この画面へのルーティングを設定します。
最初からroutes/user.jsuser.listがあるので、まずはそこを利用します。

exports.list = function(req, res){
    res.render('users');
};

ここで、サーバを再起動してみます。変更の度に何度も再起動するのは手間なので、変更を自動で反映してくれるsupervisorというパッケージを利用すると便利です。

$ npm install -g supervisor

supervisorで再起動します。

$ supervisor app

登録が成功すると"created"と表示されます。
(データが保存されていることはMongoDBのコンソールで確認できます)

5) Userリストを表示する

作成したユーザデータを表示します。
routes/user.jsのlistを変更して、MongoDBからデータを取得します。

exports.list = function(req, res){
  User.find({}, function(err, users) {
      res.render('users', {
        users: users
    });
  })
};

次に、リスト表示する画面を作成します。
先ほど登録で使った画面を流用します。
views/user.jsに以下を追記してください。

  h1 User Listing
  p ユーザ数: #{users.length}
    table
      tr
        td id
        td name
        td age
  if(users.length > 0)
    each user in users
      tr
        td #{user.id}
        td #{user.name}
        td #{user.age}

あとは、ユーザ登録時にこの画面を表示するようにルーティングを変更します。 create処理をした後にリスト表示処理をさせるには、redirectします。

exports.create = function(req, res){
  User.create({
    id    : req.param('id')
   ,name  : req.param('name')
   ,age   : req.param('age')
  }, function(err) {
    res.redirect("/users")
  });
};

これでページにアクセスすると、ユーザ登録/一覧表示ができるようになっているはずです。

今回のご紹介は以上です。 expressはNode.jsのWebアプリケーションフレームワークデファクトになりつつあります。そのため、そのうちRubySinatraにおけるPadrinoのように、expressを拡張したフレームワークが出てくるじゃないかと期待しています。
そういった広がりが出てくると、もっとNode.jsを使う場が広がってきますね。 ただ、Node.jsがシングルスレッドなので、フルスタックのような「重いフレームワーク」はあまり向いていないと思うので、新しいNode wayの考え方にそったエコシステムの発展が楽しみですね。