概览

从 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 的版本化和发布就不再受到中间件的影响。

随着内建的中间件被移除,你必须显式添加所有依赖的中间件来运行你的应用,简单来说需要以下步骤:

  1. 安装模块:npm install –save 模块名称
  2. 在你的应用中,使用这个模块: require( 模块名称 )
  3. 基于模块的文档来使用模块

下表列出了 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。

Express 4 更新改变文档的更多相关文章

  1. Linux命令 改变文档权限及所有者

    Linux命令 改变文档权限及所有者 chgrp :改变档案所属群组 chown :改变档案拥有者 chmod :改变档案的权限, SUID, SGID, SBIT等等的特性 chgrp说明及范例 [ ...

  2. ubuntu命令改变文档权限和所有者

    chgrp :改变档案所属群组 chown :改变档案拥有者 chmod :改变档案的权限, SUID, SGID, SBIT等等的特性,可读.可写.可执行 1 chgrp 例子 chgrp [-R] ...

  3. Laya改变文档结构后GameConfig自动生成错误问题

    原来的WeaponPanel,ItemPanel,PetPanel改变了路径,然后GameConfig还是一直生成旧的路径,因为旧路径已经不存在,所以提示报错,编译不过去. 需要把编辑模式下的改路径相 ...

  4. apache 改变文档根目录www的位置

    1.找到apache的安装目录,找到config/httpd.conf,找到DocumentRoot "D:/wamp/www/" 改成你想要的目录,例如:改成 DocumentR ...

  5. js中改变文档的层次结构(创建元素节点,添加结点,插入子节点,取代子节点,删除子节点)

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  6. MongoDB(二)创建更新删除文档

    插入并保存文档操作 用insert向目标集合插入文档,如果没有_id键则会自动添加.最后自动保存. >db.foo.insert({"bar":"baz" ...

  7. 实时更新Excel文档外部数据源的数据

    实时更新Excel文档外部数据源的数据 单元格区域.Excel 表.数据透视表或数据透视图均可以连接到外部数据源(数据源:用于连接数据库的一组存储的"源"信息.数据源包含数据库服务 ...

  8. 利用 Github Actions 自动更新 docfx 文档

    利用 Github Actions 自动更新 docfx 文档 Intro docfx 是微软出品一个 .NET API 文档框架,有一个理念是代码即文档,会根据项目代码自动生成 API 文档,即使没 ...

  9. nodejs + express 热更新

    以前node中的express框架,每次修改代码之后,都需要重新npm start 才能看到改动的效果,非常麻烦,所以这里引入nodemon模块,实现了不用重启也能自动更新这样的好处 1.全局安装no ...

随机推荐

  1. Variant OLE automation

    The Variant data type is the data type for all variables. can contain any kind of data except fixed- ...

  2. MySQL表分区技术

    MySQL表分区技术 MySQL有4种分区类型: 1.RANGE 分区 - 连续区间的分区 - 基于属于一个给定连续区间的列值,把多行分配给分区: 2.LIST 分区 - 离散区间的分区 - 类似于按 ...

  3. javascript中document.appendChild和document.body.appendChild的问题

    在IE7中 var conentDiv = document.createElement("div"); document .body .appendChild(conentDiv ...

  4. IRelationalOperator空间关系接口简介

    几何对象之间都存在某种关联关系,如包含,相等,在内部,相交,叠加等.这些关联关系的获得都可以通过IRelationalOperator接口来获得,关系运算是在两个几何对象间进行的,通过IRelatio ...

  5. unity3d 射弹基础案例

    小白本来想学cocos2dx的,然而c++难学就算了,cocos2dx对新手来说简直坑爹,于是乎转战unity3d学习js,在写出第一个游戏后兴致高多了哎. 回顾一下编辑的过程:1.建立一个cube作 ...

  6. INNO SETUP 5.5.0以上版本中文语言包

    ; *** Inno Setup version 5.5.0+ Chinese messages ***;; To download user-contributed translations of ...

  7. perl中的运算符

    字符计算的运算符

  8. HQL

    以下内容全部摘自韩顺平老师Hibernate笔记 * uniqueResult方法 如果我们检索一个对象,明确知道最多只有一个对象,则建议使用该方法: 具体用法如下: Student s=(Stude ...

  9. [整理]PCB阻抗控制

    之前一直听说PCB设计中信号完整性及阻抗方面的要求,但是本人对此还是有很多的不了解,每次和别人讨论到这里后就不知道该怎么继续就这个问题交谈下去.正巧最近手头有一点工作有这方面的一些需求,就拿来花了一点 ...

  10. Elasticsearch refresh vs. flush【转载】

    源地址:    http://www.jianshu.com/p/0e9f6346f1fe 问: 若一个新的文档索引进ES索引,则它在索引操作执行后约1s可以搜索到.然而我们可以直接调用_flush或 ...