原文地址: http://expressjs.com/migrating-4.html
概覽
從 Express 3 到Express 4 是一個巨大的變化,這意味着現存的 Express 3 應用在不更新依賴的情況下將不能工作。
這篇文章涵蓋一下內容:
- Express 4 中的變化
- 一個從 Express 3 遷移到 Express 4 的示例
- 升級到 Express 4 的應用生成器
Express 4 中的變化
主要的變化如下:
- Express 的核心和中間件系統:對 Connect 和內建中間件的依賴被移除了。所以你必須自己添加中間件。
- 路由系統
- 其它
參見:
- 4.X 中的新特性
- 從 3.X 遷移到 4.X
Express 的核心和中間件系統
Express 4 不再依賴 Connect,並且從核心中移除了所有內建的中間件,除了 express.static 之外。這意味着 Express 現在是一個不依賴路由和中間件的 Web 框架。這樣 Express 的版本化和發布就不再受到中間件的影響。
隨着內建的中間件被移除,你必須顯式添加所有依賴的中間件來運行你的應用,簡單來說需要以下步驟:
- 安裝模塊:npm install –save 模塊名稱
- 在你的應用中,使用這個模塊: require( 模塊名稱 )
- 基於模塊的文檔來使用模塊
下表列出了 Express 3 中對應 Express 4 中的模塊
Express 3 | Express 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.timeout | connect-timeout |
完整的列表見這里: https://github.com/senchalabs/connect#middleware
多數情況下,你可以使用 Express 4 中對應 Express 3 的模塊來替換老的模塊,詳細的說明見 GitHub 中文檔的說明
App.use 接受的參數
在 Express 4 中,現在你可以使用帶有一個可變參數的路徑來加載中間件,並且從路由處理器中讀取參數的值,例如:
app.use('/book/:id', function(req, res, next) { console.log('ID:', req.params.id); next(); })
路由系統
應用隱式加載路由中間件,所以,現在你不必擔心 router 路由中間件加載的次序問題。
定義路由的方式沒有發生變化,現在增加了兩個新的特性來幫助組織路由系統。
- 新的方法 route,針對一個路由路徑創建鏈式的路由處理器。
- 新的類 express.Router,創建模塊化的路由處理器
app.route 方法
新的 app.route 方法對特定的路由路徑創建鏈式的路由處理器。由於可以在一個地方定義路徑,這樣有助於創建模塊話的路由規則,減少重復。
路由的詳細信息,可以參見 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 類
另外一個幫助組織路由的特性是新的類 express.Router,可以幫助創建模塊話的路由處理器。一個 Router 的實例就是一個完整的中間件和路由系統,由於這個原因,它經常被稱為 迷你應用。
下面演示了創建一個名為 bird.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 中間件。
其它變化
下表列出了其它小的但是重要的修改
對象 |
說明 |
Node |
Express 4 需要 Node 0.10.x 及其以上版本,已經不支持 0.8.x |
http.createServer |
不再需要 http 模塊,應用使用 app.listen() 啟動 |
app.configure() |
app.configure() 已經被移除,使用 process.env.NODE_ENV 或者 app.get(“env”) 來檢測環境、配置應用 |
json.spaces() |
在 Express 4 中默認禁用了 json spaces |
Req.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 的示例。
Version 3 app
app.js
原來的 app.js 如下:
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 如下所示
{ "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. http 模塊已經使用了,所以,刪除 var http = require( "http" );
2. 內建的中間件 express.favicon, express.logger, express.methodOverride, express.session, express.bodyParser 和 express.errorHandler 已經不存在了,你必須手動安裝,然后在應用中替換它們。
3. 不再需要加載 app.router ,實際上,它也已經不是 Express 4 中的對象,所以,刪除 app.use( app.router );
4. 使用 app.listen() 來取代 http.createServer 啟動。
Version 4 app
package.json
執行上面的命令,會如下更新 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 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'))); // development only if ('development' == app.get('env')) { app.use(errorHandler()); } app.get('/', routes.index); app.get('/users', user.list); app.listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); });
運行應用
現在,遷移已經完成了,使用如下命令啟動。
$ node app
使用瀏覽器訪問 http://localhost:3000,查看使用 Express 4 生成的頁面。
升級到 Express 4 的應用生成器
生成一個 Express 4 的命令行工具還是 express,但是,升級到新版本的話,需要先卸載 Express 3 的生成器,然后安裝新的生成器。
安裝
如果你已經安裝過 Express 3 的生成器,必須先卸載
npm uninstall –g express
依賴與你的目錄權限和配置,可能需要先執行 sudo 提升權限。
現在,安裝新的生成器
Npm install –g express-generator
現在,你系統中的 express 命令已經升級為 Express 4 的生成器了。
生成器的變化
除了下面的變化,基本上與以前相同。
--sessions 選項被刪除了
--jshtml 選項被刪除了
--hogan 被添加,以便支持 Hogan.js
示例
執行下面的命令,創建 app4 應用
express app4
如果你查看 app4 文件夾中的 app.js 文件,你會發現所有的中間件被替換為獨立的中間件加載,router 中間件不再顯式加載。
你還會注意到 app.js 現在是一個 Node 模塊。
安裝依賴的文件之后,使用下面的命令啟動應用。
$ npm start
如果你查看 package.json 中的啟動腳本,你會注意到實際的啟動腳本是 node ./bin/www,在 Express 3 中是 node app.js
由於 Express 4 新生成的 app.js 已經是一個 Node 模塊,它可以不再需要通過一個獨立的應用來啟動,它可以在 Node 文件中加載,通過 Node 文件啟動,這里就是 ./bin/www
不管是 bin 文件夾,還是 www 文件,他們都是手工由 Express 生成器生成的,所以,需要的話,都可以進行修改。
為了與 Express 3 保持一致,刪除 module.experts = app;在 app.js 的最后,添加下面的代碼。
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 模塊。
var debug = require('debug')('app4');
然后將 package.json 文件中的 start: "node ./bin/www" 修改為 "start": "node app.js"。
現在,已經從 ./bin/www 回到了 app.js。