express 快速入门
简介
作为前端开发,Nodejs 已经成了很多公司对我们这一岗位的要求。
而 express 是非常受欢迎的 Nodejs Web 框架,常用于构建 Web 应用和 API。它帮助我们封装了 Nodejs 底层的 API,屏蔽了大量的繁琐的细节,让我们只需要关注业务开发就行了,极大的降低了学习的成本。
如何使用 express 快速搭建一个的后端服务,我们主要围绕以下几个部分:
- 路由
- 中间件
- 静态文件服务
- 错误处理
演示环境
- 电脑 - Windows 10
- Node - v16.15.0
- Npm - 9.4.0
- Express - 4.18.2
快速搭建后端服务
为了便于大家去理解 express 对 nodejs 做了哪些封装,在使用 express 之前,我们先来看下使用 nodejs 内置的 http 模块是怎么搭建 node 服务的。
原生 http 模块
- 创建 http-server 文件夹并进入
- 执行
npm init
命令,然后一路回车,生成 package.json 文件。 - 创建
server.js
,并添加如下代码:
const http = require('http')
const server = http.createServer((req, res) => {
res.statusCode = 200
res.setHeader('Content-Type', 'text/html')
res.end('hello world')
})
server.listen(3000, () => {
console.log('服务已启动...')
})
- 在控制台中运行:
node server.js
- 用客户端/浏览器访问服务器 http://127.0.0.1:3000
使用 express 搭建服务
- 创建 express-server 文件夹并进入。
- 执行
npm init
命令,然后一路回车,生成 package.json 文件。 - 执行
npm install express
来安装 express 模块。然后改写 server.js。 - 创建
server.js
,并添加如下代码:
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('hello world')
})
app.listen(3000, () => {
console.log('服务已启动...')
})
- 在控制台中运行:
node server.js
- 用客户端/浏览器访问服务器 http://127.0.0.1:3000
注意
express 属于第三方模块,需要先安装依赖后才能使用。
Request 和 Response 对象
Request 对象是请求对象,就是回调函数中的 req 参数,主要是网络请求中带的一些属性,比如参数, cookie 等等。
Response 对象是响应对象,就是回调函数中的 res 参数,可以执行一系列的响应操作,比如给客户端响应内容和状态等等。
查看 Request 和 Response 对象的所有 API
路由机制
思考:我们在向后端发请求时通过什么去区分接口的?
答:请求方式+接口 url
我们在 express 中,定义路由的方式是:
app.METHOD(URL, CALLBACK)
这种方式就可以通过请求方式和 URL 来帮我们区分不同的请求,从而去执行不同的响应。
nodemon
nodemon 能够检测工作区代码的变化,并自动重启。
执行 npm install nodemon -D
安装 nodemon,然后修改 package.json 文件中的 start 命令:
{
"name": "express-server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"start": "nodemon server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.18.2"
},
"devDependencies": {
"nodemon": "^2.0.20"
}
}
再执行 npm start
启动服务,之后我们再修改代码就不需要手动的重启服务了。
核心概念
路由
在浏览器中我们想要访问百度,只需要知道百度的地址就行了,路由也是类似的概念,我们想要知道客户端调用的是哪个接口,就是通过路由来判断的。
路由方法
Express 支持对应于 HTTP 方法的以下路由方法:get、post、put、delete 等等。
使用方法为:
app.METHOD(URL, CALLBACK)
示例:
const express = require('express')
const app = express()
// get 请求
app.get('/', (req, res) => {
res.send('hello world')
})
// post 请求
app.post('/about', (req, res) => {
res.send({ name: 'itheima', age: 18 })
})
路由路径
路由路径一般是字符串。
匹配根路径:
app.get('/', (req, res) => {
res.send('Hello World!')
})
匹配特定路径:
app.get('/user/list', (req, res) => {
res.send('User List')
})
匹配路径模式:
app.get('/user/:userId', (req, res) => {
res.send(req.params)
})
路由拆分
当我们的路由越来越多,比如有用户相关的路径,有系统相关的路径,如果不加以管理,会导致代码变得难以维护和理解。
为了解决这个问题,可以将路由处理程序拆分成多个文件,每个文件专门处理一组相关的路由,使代码更加模块化,易于维护和扩展。
拆分前
const express = require('express')
const app = express()
app.get('/user/list', (req, res) => {
res.send('User List')
})
app.get('/user/:userId', (req, res) => {
res.send(req.params)
})
app.listen(3000)
拆分后
const express = require('express')
const app = express()
const user = express.Router() // 创建子路由
user.get('/list', (req, res) => {
res.send('User List')
})
user.get('/:userId', (req, res) => {
res.send(req.params)
})
app.use('/user', user) // 注册子路由
app.listen(3000)
中间件
中间件是一个非常重要的概念,它可以在请求被路由匹配到具体的处理程序时执行一些额外的逻辑,比如处理 CORS 跨域,处理请求错误等。中间件本质上是一个函数,它们可以按照一定的顺序被执行。
在 Express 中,中间件可以通过 app.use() 方法来注册:
app.use(someMiddleware)
通过中间件实现 CORS 实现跨域:
const express = require('express')
const app = express()
// 允许跨域
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
next()
})
// ...省略
注意
如果中间件函数不调用 next() 函数,那么请求将被挂起,不会继续向下传递。
静态文件服务
在 Web 应用程序中,通常需要向客户端提供静态资源,如 HTML、CSS、JavaScript、图像、视频等文件。
为了方便地处理静态资源,Express 提供了一个内置的中间件函数 express.static()
,用于向客户端提供静态文件服务。
这个中间件函数可以将目录下的静态文件映射到一个 URL 的路径上,从而可以通过浏览器访问这些静态文件。
静态文件准备
假设我们的静态资源在 public 下面:
public
├── css
│ └── style.css
└── img
└── logo.png
中间件
在使用 express.static()
中间件函数时,需要指定静态文件所在的目录路径和 URL 的路径。
我们只需要在 server.js 中添加一行代码:
app.use(express.static('public'))
这意味着当客户端请求静态文件时,Express 将会在 public 目录下查找相应的文件并将其发送给客户端。
然后我们就可以通过下面的路径访问到这些资源了:
注意
express.static()
中间件函数只能处理静态文件,不能处理动态请求。如果需要处理动态请求,需通过路由函数来处理。
处理错误
当应用程序出现错误时,如何正确地处理错误并向用户提供有用的信息,是一个好的应用程序设计的重要方面。
我们在访问一些路由时有可能这个路由没有定义,这个时候就会返回 404 的状态码,或者服务器内部代码出错返回 500 错误码,这些情况是在开发中经常碰到的,那么服务端应该如何处理这些异常的情况呢?
在 Express 中,错误处理可以通过中间件来实现。
注意
错误处理中间件应该放在所有路由的后面。
404 错误
在 server.js 中添加如下代码:
// 处理 404 错误
app.use('*', (req, res) => {
res.status(404).send(`<h1>404 找不到你要的页面~</h1>`)
})
*
表示匹配任何路径,status(404)
表示修改状态码为 404,将此中间件放在所有路由后面,捕获路径匹配失败的请求。
再次提醒:一定是放在所有路由的后面,只有前面的路由都匹配不上才会匹配到 *
的这个路由。
处理内部错误
在 server.js 中添加如下代码:
// 处理服务器错误
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('<h1>服务器好像开小差了~</h1><p>过一会儿再试试看吧!</p>')
next()
})
//
温馨提示
- 处理服务器错误,需要四个参数,且参数的顺序固定为
err, req, res, next
。 - 处理服务器错误,建议放到 404 后面,为什么?
参考答案:如果将错误处理中间件放在 404 中间件之前,那么发生 404 错误时,错误处理中间件也会被执行,这会导致不必要的错误响应。
拓展阅读
其他 Node.js Web 框架。
如果你只想快速搭建一个模拟的后端 API,方便前端开发和测试,推荐使用 json-server
。而 express
则更适合用于构建复杂的 Web 应用程序,提供更多的自定义和扩展能力。