Express 4 の詳細

投稿日 2015/07/10

[Home] | [もどる] | [Routing の詳細] | [ミドルウェアの使用] | 

Express 4 アプリケーション

Express 4 は Express 3 と互換性はない。したがって、Express 3 アプリケーションをそのまま実行することはできない。

Express 4 アプリケーションのひな型は、express コマンドで作成する。もし、インストールされていなかったら、次のようにしてインストールする。

$ npm install express-generator -g

express コマンドの使用方法は、-h スイッチを付けて実行するとヘルプの内容が表示される。

$ express -h

Express アプリケーションのひな型は、次のようにするとフォルダ myapp が作成され、その中に必要なサブフォルダやファイルが作成される。

$ express myapp

ただし、これだけだと正しく動作しない。中で使用しているモジュールがインストールされていないためである。これらのモジュールを次のようにしてインストールする。

$ npm install

モジュールのインストールが終わったら、次のようにして実行する。

npm start

あるいは(Linuxの場合)

DEBUG=myapp npm start

ブラウザで "http://localhost:3000/" などを開いてメッセージが表示されれば、正しく動作している。


フォルダの構成

express コマンドは次のようなフォルダを作成する。


app.js

app.js は下のような最初コードになっている。コメントは元々は英語であるが日本語に修正してある。

// 外部モジュール (ミドルウェア)。npm install でインストールする必要がある。
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
// コントローラ
var routes = require('./routes/index');
var users = require('./routes/users');
// Express 4 アプリケーションオブジェクトを取得する。
var app = express();

// ビューエンジンをセットアップ
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// favicon.ico を /public に配置しない場合は、この行はコメントアウトにする。
app.use(favicon(__dirname + '/public/favicon.ico'));
// ミドルウェアをバインドする。
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// ルートの定義 (必要ならここに独自のルートを後で追加する)
app.use('/', routes);
app.use('/users', users);

// HTTP エラー 404 をキャッチし、エラーハンドラへ転送する。
app.use(function(req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// エラーハンドラ

// 開発時のエラーハンドラ
//  スタックトレースを表示
if (app.get('env') === 'development') {
    app.use(function(err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// 運用時のエラーハンドラ
//  スタックトレースの表示はしない
app.use(function(err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

// app オブジェクトを公開
module.exports = app;

ビューの編集と追加

ビューは views フォルダ内に作成する。ビューとコントローラは app.js でひもづけられる。

ビューはデフォルトでは、layout.jade と本体 (例 index.jade) からなる。layout.jade の内容はデフォルトでは次のようになっている。title はコントローラで決める変数である。

doctype html
html
 head
  title= title
  link(rel='stylesheet', href='/stylesheets/style.css')
 body
  block content

つまり、ページの共通部分を記述したものが、"layout.jade" である。よって、layout.jade を使うときは、block content の部分だけを記述すればよい。

ビューの文字コードを UTF-8 とし、よく使われる jQuery などを追加したものが下のlayout.jade である。

doctype html
html
 head
  meta(charset="utf-8")
  title= title
  // jQuery
  script(src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js")
  // Bootstrap
  link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css")
  link(rel="stylesheet", href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css")
  script(src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js")
  // AngularJS
  script(src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js")
 body
  block content

下に index.jade の例を示す。メニューバーは外部の HTML を読み込んでいる。この menubar.html も views の下に配置する。

extends layout

block content
 header
  // ページのタイトル
  h1(style="color:darkcyan;text-align:center;padding:15px;")= title
  // メニューバー
  include menubar.html
  
 // 記事
 article
  h2(style="padding-left:15px;margin-top:30px;margin-bottom:16px;margin-left:14px;")  このアプリケーションについて
  p このアプリケーションは node.js + Express 4, AngularJS, Bootstrap を使った実験的な ウェブアプリケーションである。
  
 // フッター
 footer
  p  
  p(class="text-center")
   a(href="#top") ページの先頭へ
  p  
  p  


ルータ (Router) の編集と追加

ルータは routes フォルダの下に配置する。ルータはルート (経路) に対する動作を記述するが、express コマンドが出力した index.js は次のようになっている。つまり、ルート "/" に対する動作のみが入っている。

ルータは、MVC における C (コントローラ) の役割を担う。※ V はビューであるが、M (Model) に相当する機能は Express において既定では存在しない。

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res) {
  res.render('index', { title: 'Express' });
});

module.exports = router;

Routing の詳細 ..


ルータはデフォルトでは routes/index.js であるが、複数ファイルに分けることができる。routes/users.js はその例である。

var express = require('express');
var router = express.Router();

/* GET users listing. */
router.get('/', function(req, res, next) {  // ルートが /users でなく "/" であることに注意。
  res.send('respond with a resource');
});

module.exports = router;

ルータを複数ファイルに分けるとき、app.js の修正が必要になる。つまり、下のようなコードの追加が必要である。

//   ...
// users.js を参照
var users = require('./routes/users');
//   ...
// users.js を app にバインド
app.use('/users', users);

ビュー (Jade) との連携

ビューへデータを渡すには、ルータ (例:index.js) において res.render() を実行する際に、第二パラメータとしてそのデータを渡せばよい。

router.get('/report1', function(req, res, next) {
  var test1 = db.collection('test1');
  var list = [];
  var item;
  
  test1.find().toArray(function(err, result) {
    for (var i in result) {
      item = result[i];
      list.push(item['id'] + ', ' + item['name']);
      console.info(item['id'] + ', ' + item['name']);
    }
    // ここでビューにデータを渡す。
    res.render('report1', { title: 'Report1', items: list });
  });
});

ビュー (Jade) 側では、div= ディレクティブなどで、その変数の値を HTML に埋め込む。コレクションの場合は、each x in collection ディレクティブなどを使用する。

h1= title
ul
 each x in items
  li= x

リクエストオブジェクト (request)

リクエストオブジェクトはハンドラの引数 req として取得できる。

app.get('/user/:id', function(req, res){
  res.send('user ' + req.params.id);
});

特に、外部から来る引数 (パスやフォームのデータ) を取得するには、req のメンバを利用する。

よく使われるメンバを示す。

Express 4.x API (Request)

req.query の使用例

/* GET JSON  /query/collections */
router.get('/query/collections', function(req, res) {
  var db = mongo.db('mongodb://localhost:27017/' + req.query.dbname);
  db.collectionNames({namesOnly:true}, function(err, result) {
    res.json(result);
    db.close();
  });
});

req.body の使用例

router.post('/collections', function(req, res) {
  var dbname = req.body.dbname;
  var db = mongo.db('mongodb://localhost:27017/' + dbname);
  db.collectionNames(function(err, result) {
    var colnames = new Array();
    for (var i in result) {
      colnames.push(result[i].name);
    }
    res.render('collections', {
      title: "Collections in DB: " + dbname,
      names: colnames,
      dbs: req.session.dbs,
      database: dbname,
      page:1 });
    db.close();
  });
});

req.params の使用例

router.get('/collections/:name', function(req, res) {
  var database = req.params.name;
  var db = mongo.db('mongodb://localhost:27017/' + database);
  db.collectionNames(function(err, result) {
    var colnames = new Array();
    for (var i in result) {
      colnames.push(result[i].name);
    }
    res.render('collections', {
       title:"Collections in DB: " + database,
       database: database,
       names: colnames,
       dbs: req.session.dbs,
       page:1 });  
    db.close();
  });
});

レスポンスオブジェクト (response)

レスポンスオブジェクトはハンドラの引数 res として取得できる。

app.get('/user/:id', function(req, res){
  res.send('user ' + req.params.id);
});

クライアントに応答を返すには、res のメソッドを使用する。よく使われるメソッドを以下に示す。

Express 4.x API (Response)


アプリケーションオブジェクト

アプリケーションオブジェクトはトップレベルの関数 express() で取得する。

var express = require('express');
var app = express();

app.get('/', function(req, res){
  res.send('hello world');
});

app.listen(3000);

よく使われるメソッドを以下に示す。

Express 4.x API (Application)


セッション

Express 4 では、セッションの管理に express-session ミドルウェア を使用する。これは、ビルトインでないので、次のようにしてインストールする。

$ npm install express-session

使用例。ここで、secret:"...." の ... は任意の文字列である。また、maxAge の単位はミリ秒である。時間指定を省略すると、ブラウザが閉じるまでになる。

app.js

var session = require('express-session');  // Session 機能
...
app.use(session({ secret: '19898989', resave: true, saveUninitialized: true }));

router/index.js (セッション変数への代入例)

router.get('/', function(req, res) {
  var db = mongo.db('mongodb://localhost:27017');
  var admin = db.admin();
  admin.listDatabases(function(err, result) {
    var dbnames = new Array();
    for (var i in result.databases) {
      dbnames.push(result.databases[i].name);
    }
    req.session.dbs = dbnames;
    res.render('index', { title: 'MongoDB Info', dbs: result.databases, page:0 });
    db.close();
  });
});  

router/index.js (セッション変数の使用例)

router.get('/collections', function(req, res) {
  var db = mongo.db('mongodb://localhost:27017');
  res.render('collections', { title: "Collections", names: [], dbs: req.session.dbs, database: "", page:1 });
});

MongoDB の使用

Express では JavaScript と親和性の高い MongoDB を利用すると処理が何かと簡単になる。MongoDB を使うには、ミドルウェアのインストールが必要になる。

$ npm install mongoskin

MongoDB のコレクションのデータを取得する例

var db = require('mongoskin').db('localhost:27017/animals');

db.collection('mamals').find().toArray(function(err, result) {
  if (err) throw err;
  console.log(result);
});

MongoDB のコレクションにデータを追加する例

router.post('/form1', function(req, res, next) {
  var test1 = db.collection('users');
  test1.insert(req.body, function(error, resultArray) {
    console.log("inserted new user");
  });
  res.render('form1', { title: 'Form1', result:'OK ' + req.body['id'] + ", " + req.body['name']});
});

(参考) Database integration


SQLite3 の使用

SQLite3 を使用する場合は、次のコマンドでミドルウェアのインストールが必要になる。

$ npm install sqlite3

下の例はメモリ上のテーブルにクエリを行う例である。

var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database(':memory:');

db.serialize(function() {

  db.run('CREATE TABLE lorem (info TEXT)');
  var stmt = db.prepare('INSERT INTO lorem VALUES (?)');
  
  for (var i = 0; i < 10; i++) {
    stmt.run('Ipsum ' + i);
  }
  
  stmt.finalize();
  
  db.each('SELECT rowid AS id, info FROM lorem', function(err, row) {
    console.log(row.id + ': ' + row.info);
  });
});

db.close();

 

 


 

 開設 2014年12月   著作権 2014-2015 bonk.red  連絡先: こちらからメッセージを送ってください。

 このページの先頭へ..