Express 是基于 Node.js 平台,快速、开放、极简的 web 开发框架
基本使用
安装
npm install express --save
示例代码
const express = require('express')
const app = express()
const port = 3000app.get('/', (req, res) => {res.send('Hello World!')
})app.listen(port, () => {console.log(`Example app listening on port ${port}`)
})
Express 官方推荐脚手架
通过应用生成器工具 express-generator 可以快速创建一个应用的骨架。
你可以通过 npx (包含在 Node.js 8.2.0 及更高版本中)命令来运行 Express 应用程序生成器。
npx express-generator
命令行参数
-h, --help 输出使用方法--version 输出版本号-e, --ejs 添加对 ejs 模板引擎的支持--hbs 添加对 handlebars 模板引擎的支持--pug 添加对 pug 模板引擎的支持-H, --hogan 添加对 hogan.js 模板引擎的支持--no-view 创建不带视图引擎的项目-v, --view <engine> 添加对视图引擎(view) <engine> 的支持 (ejs|hbs|hjs|jade|pug|twig|vash) (默认是 jade 模板引擎)-c, --css <engine> 添加样式表引擎 <engine> 的支持 (less|stylus|compass|sass) (默认是普通的 css 文件)--git 添加 .gitignore-f, --force 强制在非空目录下创建
启动应用
- 在 MacOS 或 Linux 中
DEBUG=myapp:* npm start
- Windows 命令行中
set DEBUG=myapp:* & npm start
- Windows 的 PowerShell 中
$env:DEBUG='myapp:*'; npm start
然后在浏览器中打开 http://localhost:3000/ 网址就可以看到这个应用了。
如何利用 Express 托管静态文件
express.static 内置中间件函数可以为我们提供 图像、CSS 文件和 JavaScript 文件之类的静态文件托管
express.static(root, [options])
多个静态资源目录,请多次调用 express.static 中间件函数:
app.use(express.static('public'))
app.use(express.static('files'))
路由
路由指的是确定应用程序如何响应对特定端点的客户机请求,这是一个URI(或路径)和一个特定的HTTP请求方法(GET、POST等)。
每个路由都可以有一个或多个handler函数,这些函数在匹配路由时执行。
路由定义采用以下结构
app.METHOD(PATH, HANDLER)
- app: express的一个实例。
- METHOD:
- HTTP请求方法,小写(支持所有的http请求方法,特殊请求方法 all , 用于在所有HTTP请求方法的路径上加载中间件函数)。
- PATH:
- 路由路径,可以是字符串、字符串模式或正则表达式。
- 如果需要在路径字符串中使用美元字符( ) ,请将其转义后用 ( [ a n d ] ) 括起来。例如 , / d a t a / ),请将其转义后用([and])括起来。例如, /data/ ),请将其转义后用([and])括起来。例如,/data/book 请求的路径字符串将是
/data/([\$])book
。
- HANDLER:
- 匹配路由时执行的函数。
- 可以提供多个行为类似中间件的回调函数来处理请求。唯一的例外是,这些回调可能会调用next(‘route’)来绕过剩余的路由回调。您可以使用这种机制在路由上施加前置条件,然后在没有理由继续当前路由时将控制权传递给后续路由。
app.get('/example/b', (req, res, next) => {console.log('the response will be sent by the next function ...')next()
}, (req, res) => {res.send('Hello from B!')
})
app.route
app.route() 为路由路径创建可链接的路由处理程序。由于路径是在单个位置指定的,因此创建模块化路由很有帮助,还可以减少冗余和错别字。
下面是一个用app.route()定义的链式路由处理程序的例子。
app.route('/book').get((req, res) => {res.send('Get a random book')}).post((req, res) => {res.send('Add a book')}).put((req, res) => {res.send('Update the book')})
express.Router
express.Route 可以将路由器创建为一个模块,在其中加载一个中间件函数,定义一些路由,并将路由器模块挂载到主应用的某个路径上
const express = require('express')
const router = express.Router()
const app = express()// middleware that is specific to this router
router.use((req, res, next) => {console.log('Time: ', Date.now())next()
})
// define the home page route
router.get('/', (req, res) => {res.send('Birds home page')
})
// define the about route
router.get('/about', (req, res) => {res.send('About birds')
})app.use('/pub', router)
中间件
中间件是可以访问请求对象( req)、响应对象( res) 以及next应用程序请求-响应周期中的函数。该next函数是 Express 路由器中的一个函数,当被调用时,它会执行当前中间件之后的中间件。
如果当前的中间件函数没有结束请求,则必须调用next()将控制权传递给下一个中间件函数。否则,请求将被挂起。
中间件加载的顺序很重要:首先加载的中间件函数也首先执行
如何使用中间件
- 应用层
const express = require('express')
const app = express()app.use((req, res, next) => {console.log('Time:', Date.now())next()
})
- 路由层
const express = require('express')
const app = express()
const router = express.Router()// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {console.log('Time:', Date.now())next()
})
- 错误处理中间件
app.use((err, req, res, next) => {console.error(err.stack)res.status(500).send('Something broke!')
})
-
内置中间件
- express.static提供静态资源,例如 HTML 文件、图像等。
- express.json使用 JSON 有效负载解析传入请求。注意:适用于 Express 4.16.0+
- express.urlencoded使用 URL 编码的有效负载解析传入请求。注意:适用于 Express 4.16.0+
如何覆盖 Express API
Express API 由请求和响应对象的各种方法和属性组成。这些都是通过原型继承的。Express API 有两个扩展点:
- 全局原型位于 express.request 和 express.response
- 特定原型位于 app.request 和 app.response
覆盖方法
app.response.sendStatus = function (statusCode, type, message) {// code is intentionally kept simple for demonstration purposereturn this.contentType(type).status(statusCode).send(message)
}
覆盖属性
Object.defineProperty(app.request, 'ip', {configurable: true,enumerable: true,get () { return this.get('Client-IP') }
})