StrongLoop が提供する Express と Node.js に関する研修

StrongLoop / IBMによって提供されるこの翻訳.

本書は、英語の資料と比較すると古くなっている可能性があります。最新の更新については、英語版の資料を参照してください。

Express 4 への移行

概説

Express 4 では、Express 3 とは互換性のない変更が行われています。つまり、依存関係にある Express のバージョンを更新すると、既存の Express 3 アプリケーションは機能しません。

この記事では以下の内容を扱います。

Express 4 における変更点

Express 4 では、いくつかの大きな変更が行われています。

以下も参照してください。

Express コアおよびミドルウェア・システムの変更

Express 4 は、Connect に依存しなくなり、express.static 関数を除くすべての標準装備ミドルウェアをコアから削除しました。つまり、Express は独立したルーティングおよびミドルウェアの Web フレームワークになり、Express のバージョン管理とリリースはミドルウェア更新の影響を受けません。

標準装備ミドルウェアがないため、アプリケーションの実行に必要なすべてのミドルウェアを明示的に追加する必要があります。そのためには、単に以下のステップを実行してください。

  1. モジュールをインストールします。npm install --save <module-name>
  2. アプリケーションでモジュールを要求します。require('module-name')
  3. モジュールの資料に従ってモジュールを使用します。app.use( ... )

次の表に、Express 3 のミドルウェアと、それぞれに対応する Express 4 のミドルウェアをリストします。

Express 3Express 4
express.bodyParser body-parser + multer
express.compress compression
express.cookieSession cookie-session
express.cookieParser cookie-parser
express.logger morgan
express.session express-session
express.favicon serve-favicon
express.responseTime response-time
express.errorHandler errorhandler
express.methodOverride method-override
express.timeout connect-timeout
express.vhost vhost
express.csrf csurf
express.directory serve-index
express.static serve-static

Express 4 のミドルウェアの完全なリストは、ここを参照してください。

ほとんどの場合、旧バージョン 3 のミドルウェアを単に Express 4 のミドルウェアに置き換えるだけですみます。詳細については、GitHub でモジュールの資料を参照してください。

app.use がパラメーターを受け入れます

バージョン 4 では、変数パラメーターを使用して、ミドルウェア関数がロードされるパスを定義し、ルート・ハンドラーからパラメーターの値を読み取ることができます。 次に例を示します。


app.use('/book/:id', function(req, res, next) {
  console.log('ID:', req.params.id);
  next();
});

ルーティング・システム

アプリケーションがルーティング・ミドルウェアを暗黙的にロードするようになったため、router ミドルウェアに関してミドルウェアがロードされる順序を考慮する必要がなくなりました。

ルートの定義方法は変わりませんが、ルーティング・システムには、ルートの編成に役立つ 2 つの新機能があります。

app.route() メソッド

新しい app.route() メソッドを使用すると、ルート・パスのチェーン可能なルート・ハンドラーを作成できます。パスは単一の場所で指定されるため、モジュール式のルートを作成すると、便利であるほか、冗長性とタイプミスを減らすことができます。ルートについて詳しくは、Router() 資料を参照してください。

次に、app.route() 関数を使用して定義された、チェーニングされたルート・ハンドラーの例を示します。


app.route('/book')
  .get(function(req, res) {
    res.send('Get a random book');
  })
  .post(function(req, res) {
    res.send('Add a book');
  })
  .put(function(req, res) {
    res.send('Update the book');
  });

express.Router クラス

ルートの編成に役立つもう 1 つの機能は、新しいクラス express.Router です。これを使用すると、モジュール式のマウント可能なルート・ハンドラーを作成できます。Router インスタンスは、完全なミドルウェアおよびルーティング・システムです。そのため、よく「ミニアプリケーション」と呼ばれます。

次の例では、ルーターをモジュールとして作成し、その中にミドルウェアをロードして、いくつかのルートを定義し、それをメインアプリケーションのパスにマウントします。

例えば、アプリケーション・ディレクトリーに次の内容で birds.js というルーター・ファイルを作成します。


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

// middleware specific to this router
router.use(function timeLog(req, res, next) {
  console.log('Time: ', Date.now());
  next();
});
// define the home page route
router.get('/', function(req, res) {
  res.send('Birds home page');
});
// define the about route
router.get('/about', function(req, res) {
  res.send('About birds');
});

module.exports = router;

次に、ルーター・モジュールをアプリケーションにロードします。


var birds = require('./birds');
...
app.use('/birds', birds);

これで、アプリケーションは、/birds および /birds/about のパスに対する要求を処理できるようになり、ルートに固有の timeLog ミドルウェアを呼び出します。

その他の変更点

次の表に、Express 4 におけるその他の小規模ながらも重要な変更点をリストします。

オブジェクト 説明
Node.js Express 4 には、Node.js 0.10.x 以降が必要です。Node.js 0.8.x に対するサポートは除去されました。

http.createServer()

http モジュールは、このモジュールを直接処理する必要がある場合を除き、不要になりました (socket.io/SPDY/HTTPS)。アプリケーションは、app.listen() 関数を使用して開始できます。

app.configure()

app.configure() 関数は削除されました。環境を検出して、アプリケーションを適宜に構成するには、process.env.NODE_ENV 関数または app.get('env') 関数を使用してください。

json spaces

json spaces アプリケーション・プロパティーは、Express 4 ではデフォルトで無効になっています。

req.accepted()

req.accepts()req.acceptsEncodings()req.acceptsCharsets()、および req.acceptsLanguages() を使用してください。

res.location()

相対 URL を解決しなくなりました。

req.params

以前は配列でしたが、現在ではオブジェクトになりました。

res.locals

以前は関数でしたが、現在ではオブジェクトになりました。

res.headerSent

res.headersSent に変更されました。

app.route

今後は app.mountpath として使用できます。

res.on('header')

削除されました。

res.charset

削除されました。

res.setHeader('Set-Cookie', val)

機能が基本的な Cookie 値の設定に限定されるようになりました。機能を追加するには、res.cookie() を使用してください。

移行の例

次に、Express 3 アプリケーションを Express 4 に移行する例を示します。 使用しているファイルは、app.js および package.json です。

バージョン 3 アプリケーション

app.js

次の app.js ファイルを使用する Express v.3 アプリケーションがあるとします。


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.methodOverride());
app.use(express.session({ secret: 'your secret here' }));
app.use(express.bodyParser());
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'));
});

package.json

付随するバージョン 3 の package.json ファイルの内容は次のようになります。


{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "3.12.0",
    "jade": "*"
  }
}

プロセス

移行プロセスを開始するには、次のコマンドを使用して、Express 4 アプリケーションに必要なミドルウェアをインストールし、Express と Jade をそれぞれの最新バージョンに更新します。


$ npm install serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest jade@latest --save

app.js に以下の変更を加えます。

  1. 標準装備の Express ミドルウェア関数 express.faviconexpress.loggerexpress.methodOverrideexpress.sessionexpress.bodyParser、および express.errorHandlerexpress オブジェクトで使用できなくなりました。代わりの関数を手動でインストールして、アプリケーションにロードする必要があります。

  2. app.router 関数をロードする必要がなくなりました。この関数は有効な Express 4 アプリケーション・オブジェクトではないため、app.use(app.router); コードを削除してください。

  3. ミドルウェア関数が正しい順序でロードされていることを確認してください。つまり、アプリケーション・ルートをロードした後で errorHandler をロードしてください。

バージョン 4 アプリケーション

package.json

上記の npm コマンドを実行すると、package.json が次のように更新されます。


{
  "name": "application-name",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "body-parser": "^1.5.2",
    "errorhandler": "^1.1.1",
    "express": "^4.8.0",
    "express-session": "^1.7.2",
    "jade": "^1.5.0",
    "method-override": "^2.1.2",
    "morgan": "^1.2.2",
    "multer": "^0.1.3",
    "serve-favicon": "^2.0.1"
  }
}

app.js

次に、無効なコードを削除して、必要なミドルウェアをロードし、必要に応じてその他の変更を行います。app.js ファイルの内容は次のようになります。


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

var favicon = require('serve-favicon');
var logger = require('morgan');
var methodOverride = require('method-override');
var session = require('express-session');
var bodyParser = require('body-parser');
var multer = require('multer');
var errorHandler = require('errorhandler');

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(favicon(__dirname + '/public/favicon.ico'));
app.use(logger('dev'));
app.use(methodOverride());
app.use(session({ resave: true,
                  saveUninitialized: true,
                  secret: 'uwotm8' }));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(multer());
app.use(express.static(path.join(__dirname, 'public')));

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

// error handling middleware should be loaded after the loading the routes
if ('development' == app.get('env')) {
  app.use(errorHandler());
}

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

http モジュール (socket.io/SPDY/HTTPS) を直接処理する必要がある場合を除き、このモジュールをロードする必要はありません。次のようにして、アプリケーションを簡単に開始できます。

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

アプリケーションの実行

これで移行プロセスは完了して、アプリケーションは Express 4 アプリケーションになりました。確認するには、次のコマンドを使用してアプリケーションを開始します。


$ node .

http://localhost:3000 をロードして、Express 4 によってレンダリングされるホーム・ページを確認します。

Express 4 アプリケーション・ジェネレーターへのアップグレード

Express アプリケーションを生成するためのコマンド・ライン・ツールは引き続き express ですが、新規バージョンにアップグレードするには、Express 3 アプリケーション・ジェネレーターをアンインストールしてから、新しい express-generator をインストールする必要があります。

インストール

システムに Express 3 アプリケーション・ジェネレーターがインストールされている場合は、次のようにしてアンインストールする必要があります。


$ npm uninstall -g express

ファイルおよびディレクトリーの特権が構成されている方法によっては、このコマンドを sudo で実行することが必要になる場合があります。 次に、新しいジェネレーターをインストールします。


$ npm install -g express-generator

ファイルおよびディレクトリーの特権が構成されている方法によっては、このコマンドを sudo で実行することが必要になる場合があります。

これで、システム上の express コマンドは Express 4 ジェネレーターに更新されました。

アプリケーション・ジェネレーターの変更

コマンドのオプションと使用法の大部分は以前と同じですが、以下の例外があります。

次のコマンドを実行して、Express 4 アプリケーションを作成します。


$ express app4

app4/app.js ファイルの内容を見ると、アプリケーションに必要な (express.static を除く) すべてのミドルウェア関数が独立したモジュールとしてロードされており、router ミドルウェアがアプリケーションに明示的にロードされなくなったことが分かります。

また、app.js ファイルが Node.js モジュールになったことも分かります。対照的に以前はジェネレーターによって生成されるスタンドアロン・モジュールでした。

依存関係をインストールした後、次のコマンドを使用してアプリケーションを開始します。


$ npm start

package.json ファイルで npm start スクリプトを見ると、アプリケーションを開始する実際のコマンドは node ./bin/www であることが分かります。これは、Express 3 では node app.js でした。

Express 4 ジェネレーターによって生成される app.js ファイルが Node.js モジュールになったため、(コードを変更しない限り) アプリケーションとして単独では開始できなくなりました。モジュールを Node.js ファイルにロードして、Node.js ファイルから開始する必要があります。この場合、Node.js ファイルは ./bin/www です。

Express アプリケーションの作成またはアプリケーションの開始のために、bin ディレクトリーも、拡張子のない www ファイルも必須ではありません。これらは単にジェネレーターが推奨するものであるため、ニーズに合わせて自由に変更してください。

www ディレクトリーを削除して、処理を「Express 3 の方法」で実行するには、app.js ファイルの最後にある module.exports = app; という行を削除して、その場所に以下のコードを貼り付けます。


app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function() {
  debug('Express server listening on port ' + server.address().port);
});

次のコードを使用して debug モジュールを app.js ファイルの先頭にロードしたことを確認します。


var debug = require('debug')('app4');

次に、package.json ファイル内の "start": "node ./bin/www""start": "node app.js" に変更します。

これで、./bin/www の機能を app.js に戻しました。この変更は推奨されるものではありませんが、この演習により、./bin/www ファイルの仕組みと、app.js ファイルが単独で開始されなくなった理由を理解できます。