Fool Pool

ハマった記

Express使ってみた。

この前はクラウド上で Node.js を使ったので、今度はローカルで構築してみる。

構築と行っても、コマンドで自動的にインストールできるのが現代のフレームワークの良い所。

Nvm のインストール

Nvm -- Node Version Manager

いろんなバージョンのノードを管理できるシェルスクリプトツール。

ここからダウンロードする。 --> https://github.com/creationix/nvm

1) install.sh を実行

$ curl https://raw.github.com/creationix/nvm/v0.3.0/install.sh | sh

install.sh を実行すると、 HOME 以下に .nvm というディレクトリができ、そこにソース一式がインストールされる。

~/.nvm

Node.js のコンパイル

現時点での最新バージョン v0.10.26 をコンパイルする。なお、C++で書かれたソースをコンパイルする必要があるので、Macの場合はXCodeがインストールされていることが条件。

$ nvm install v0.10.26
######################################################################## 100.0%
Now using node v0.10.26

Express をインストールする

npm -- Node Package Manager というのがあり、パッケージを自動的にインストールしてくれる。

$ mkdir hello; cd hello
$ npm install express <-- local install

or

$ npm install -g express <-- grobal install

何もオプションを指定しないとカレントディレクトリ(=プロジェクトディレクトリ)の下の node_modules 以下にモジュールがインストールされる。

プロジェクトテンプレートの生成

今時のフレームワークは、プロジェクトテンプレートも自動で生成してくれる。

$ express -t sample

テンプレートというのは、プロジェクトに必要な構成のひな形のこと。上記を実行すると、sampleディレクトリ配下に、以下のようなフォルダ構成が生成される:

  • app.js -- サーバプログラム(エントリポイント)
  • node_modules -- 拡張モジュール
  • package.json -- プロジェクト構成ファイル
  • public -- css とか javascript とか画像とかを格納するフォルダ
  • routes -- ルータ(/ とか /post とかに対応して呼び出すプロセスを指定)
  • views -- 画面の構成とレイアウト(MVCフレームワークの View に相当)

ひな形プロジェクトが必要とするモジュールをインストールする $ npm install

サーバ起動

$ node app.js

ブラウザから http://localhost:3000 にアクセス。

f:id:nakamine11:20140327205340p:plain

ちなみに、PORT という環境変数が指定されていれば、そのポートを使うようになっている。

ソースコード

フロントからバックエンドの順に載せる。

フロントエンド

*.jade というファイル形式で記述する。

  • view/index.jade
extends layout

block content
  h1= title
  p Welcome to #{title}
  • view/layout.jade
doctype html
html
  head
    title= title
    link(rel='stylesheet', href='/stylesheets/style.css')
  body
    block content

このように、インデントで要素同士の入れ子構造を記述する。 ちなみに、生成されたHTMLは以下:

<!DOCTYPE html>
<html><head><title>Express</title>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<h1>Express</h1>
<p>Welcome to Express</p>
</body>
</html>

ルータ

action パラメータ(/ とか /post)に対応する処理を記述する。 ひな形では、ルータに直接リクエストハンドラを記述している。厳密に抽象化するのであれば、ルータは action パラメータ(/ とか /post)とリクエストハンドラの対応のみを記述すべきだが、ここではルータとリクエストハンドラは分離されていない。

  • routes/index.js
/*
 * GET home page.
 */

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

上記は、「/ が指定されたら、view/index.jade をパラメータ title = 'Express' で描画して」の意味。

  • routes/users.js
/*
 * GET users listing.
 */

exports.list = function(req, res){
  res.send("respond with a resource");
};

「/users というパラメータが指定されたら、"respond with a resource" という文字列を表示せよ」の意味。

バックエンド(アプリケーションサーバ

どうやってサーバを起動するか、どのように次のレイヤにデータを渡すか、といったことが記述されている。

  • app.js
/**
 * Module dependencies.
 */

var express = require('express');
var routes = require('./routes');
var user = require('./routes/user');
var http = require('http');
var path = require('path');

var app = express();

// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));

// development only
if ('development' == app.get('env')) {
  app.use(express.errorHandler());
}

app.get('/', routes.index);
app.get('/users', user.list);

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express server listening on port ' + app.get('port'));
});