前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket

# Express

30 秒速记

  • 核心就两件事:路由(方法 + 路径 → 处理函数)和中间件(按注册顺序串起来的函数链)
  • 取参三处:路径参数 req.params、查询串 req.query、请求体 req.body(要先挂解析中间件)
  • 宽的中间件和通配路由会吞掉后面的请求,具体的放前面,兜底的放最后
  • 外部输入一律当字符串看,进业务前做校验和类型转换
  • Express 4 里 async 处理器抛错不会自动进错误处理,Express 5 才会

Express 就是一个轻量的路由加中间件框架,理解了「按注册顺序过一条函数链」,大部分问题都能推出来。 比如为什么 404 兜底要写最后、为什么跨域中间件要写最前、为什么 req.body 是 undefined(解析中间件没挂或挂晚了)。取参记住三个位置就够了:req.params、req.query、req.body,它们全是客户端给的,?id=abc 进来就是字符串 'abc',不校验就直接查库迟早出事。版本上要留意,Express 5 才会把 async 函数里的异常自动交给错误处理,4 里要自己 try/catch 再 next(err)。

理解「Express」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 middleware 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

Express 的设计非常薄,核心只有三样东西:app、中间件、路由。app 本身就是一个函数,签名是 (req, res),所以可以直接丢给 http.createServer(app)。中间件是 (req, res, next) => {} 形式的函数,app.use() 和 app.get() 这类方法都是往内部的一个数组里追加「层」,请求进来就从头到尾挨个匹配。

const express = require('express')
const app = express()

app.use((req, res, next) => {          // 1. 所有请求都先经过这里
  console.log(req.method, req.url)
  next()                               // 不调就会挂住
})

app.use(express.json())                // 2. 解析 JSON 请求体,之后 req.body 才有值

app.get('/users/:id', (req, res) => {  // 3. 只处理 GET /users/xxx
  res.json({ id: req.params.id, tab: req.query.tab })
})

app.use((req, res) => res.status(404).json({ msg: 'Not Found' }))   // 4. 兜底
app.use((err, req, res, next) => res.status(500).json({ msg: err.message })) // 5. 错误处理

app.listen(3000)
// GET /users/7?tab=post → {"id":"7","tab":"post"},注意 id 是字符串 "7"
@前端进阶之旅: 代码已经复制到剪贴板

这段代码基本覆盖了日常 Express 的全部骨架。顺序有讲究:日志在最前面才能记到所有请求;express.json() 要在用到 req.body 的路由之前;404 必须在所有路由之后,否则会把正常请求截走;错误处理放最后,而且必须写满四个参数。

Express 4.16 起,express.json() 和 express.urlencoded() 已经内置,不用再单独装 body-parser。Express 5 在 2024 年正式发布,主要变化是 async 处理器的异常会自动交给错误处理、路由路径语法更严格、移除了 res.send(200) 这类老签名,老项目升级前要过一遍迁移说明。

面试官追问

追问 1Express 4 里 async 路由查库抛错,请求直接挂住,为什么?
参考回答

Express 4 不认识 Promise,async 函数里抛的错变成了未处理的 rejection,没人调 next(err)。要么每个处理器 try/catch 后 next(err),要么用 express-async-errors 打补丁,要么升到 Express 5,它会自动把 rejected 的 Promise 交给错误处理。

追问 2/users/:id 和 /users/me 两个路由,访问 /users/me 进了第一个,怎么办?
参考回答

:id 能匹配任何一段,先注册就先命中,req.params.id 变成 'me'。把 /users/me 写在前面,或者给参数加约束;Express 4 可以写 /users/:id(\\d+),Express 5 换了路由语法,不再支持这种正则写法,要在处理器里自己校验。

追问 3req.query.page 拿来直接 page * 10 算分页,有什么坑?
参考回答

它是字符串,'2' * 10 恰好能隐式转成 20,但 '2' + 1 就是 '21',?page=abc 会算出 NaN,?page[]=1 甚至会变成数组。进业务前统一转换:const page = Math.max(1, Number.parseInt(req.query.page, 10) || 1),复杂的用 zod 一类的 schema 校验。

追问 4一个请求进来,Express 内部大概是怎么走的?
参考回答

app 收到请求后遍历内部的 stack,按顺序拿每一层去匹配路径和方法,匹配上就调用,调用里的 next() 就是「接着往后找下一层」。传了错误就跳过普通层,只找四参数的错误处理层,全部找完都没人响应就走默认的 404。

# Express 基础应用

30 秒速记

  • Express 是第三方包,要 npm install express 并写进 package.json,不是 Node.js 自带的
  • 定位类似前端的 jQuery:把原生 http 模块包一层,让写服务端更省事
  • 原生要自己解析 URL、拼响应头、判断方法;Express 给了路由、中间件、res.send / res.json
  • 它很「薄」,不管目录结构、不带 ORM,大项目常在它上面再搭一层或换 NestJS / Egg

Express 是 Node.js 生态里最老牌的 Web 框架,作用就像 jQuery 之于 DOM:底层能力还是 http 模块,它只是让常见操作变短。 用原生写一个带两个路由的服务,你得自己 if (req.url === ...)、自己设 Content-Type、自己 JSON.stringify;换成 Express,app.get('/', ...) 加 res.json(obj) 两行就完了。它的优点是简单、生态大,缺点也是太简单,项目结构、参数校验、依赖注入都得自己定,所以团队项目里我会先约定好目录和中间件,不然很快就乱。

Express 是一个第三方模块,对原生模块封装了一套更灵活、更简洁的应用框架,其在 Node.js 环境的地位和作用好比 jQuery 在前端的地位和作用。

理解「Express 基础应用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 middleware 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1新人说 Express 是 Node.js 内置的,就没写进 package.json,有什么问题?
参考回答

Express 是第三方包,没声明依赖,换台机器或者 CI 里 npm ci 一跑,启动就报 Cannot find module 'express'。他本机能跑,多半是上级目录或全局恰好装过。依赖必须写进 dependencies。

追问 2原生 http 写一个返回 JSON 的接口,和 Express 比差在哪?
参考回答

原生要写 res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)),路由靠 if 判断 req.url 和 req.method。Express 一句 res.json(data) 搞定,路由、查询串解析、404 都有现成的。

追问 3CI 报找不到 express,同事说全局装一下就好,你同意吗?
参考回答

不同意。require 默认不会去全局目录找包,全局装了也不一定能解决,就算碰巧好了也是把环境差异藏起来了。正确做法是把它写进项目依赖,提交 lock 文件,CI 用 npm ci 装。

追问 4新项目还会选 Express 吗?
参考回答

看规模。小服务、BFF、脚本型接口用 Express 足够,资料多上手快。团队大、要强约定和分层,就考虑 NestJS;追求性能和 schema 校验一体化,可以看 Fastify。

# 路由

30 秒速记

  • 路由 = 把「请求方法 +
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
  • 基础篇

    • 环境搭建
    • node部署
    • 基础应用
  • 内置模块

    • 1.0 本地路径处理 path
    • 2.0 文件系统操作 fs
    • 3.1 基础调试 console
    • 3.2 本地调试远程服务器上的Node代码
    • 4.1 网络服务 http
    • 4.2 网络服务 http res
    • 4.3 网络服务 http req
    • 4.4 网络服务 http server
    • 4.5 网络服务 http client
    • 4.6 网络服务 https
    • 4.7 网络TCP net
    • 4.8 网络UDP dgram
    • 4.9 域名解析 dns
    • 5.0 网络地址解析 url
    • 5.1 URL查询字符串 querystring
    • 6.1 流操作 stream
    • 6.2 逐行读取 readline
    • 7.1 进程相关 process
    • 7.2 子进程 child
    • 8.1 二进制数据 buffer
    • 8.2 二进制解码 string_decoder
    • 9.1 事件机制 events
    • 9.2 实用工具模块 util
    • 9.3 数据加密 crypto
    • 9.4 MD5入门介绍及crypto模块的应用
    • 9.4 资源压缩 zlib
    • 9.5 集群 cluster
    • 9.6 v8
  • 进阶篇

    • 5分钟入门非对称加密用法
    • cluster
    • cookie_parser深入
    • crypto模块之理论篇
    • express+cookie_parser签名机制深入剖析
    • express+session实现简易身份认证
    • https
    • log4js入门实例
    • node8_napi
    • 使用 async 控制并发
    • 使用 eventproxy 控制并发
    • 使用 superagent 与 cheerio 完成简单爬虫
    • 基于express+muter的文件上传
    • 将图片转成datauri嵌入到html
    • 常用中间件 body_parser 实现解析
    • 日志模块morgan
    • 服务端字符编解码&乱码处理 charset_enc_dec
    • 测试用例mocha,should,istanbul
    • 调试日志打印debug模块
  • Express

    • 1.1 Express概览篇
    • 1.2 Express
      • Express 基础应用
        • 路由
        • Express 使用
        • GET
        • POST
        • 跨域支持(放在最前面)
      • Express Koa 和 Egg 基础配置
      • Express 过滤器
      • Express 文件上传
      • Express https服务器
  • Koa2

    • 1.0 koa2概览篇
    • 1.1 快速开始
    • 1.2 async await使用
    • 1.3 koa2简析结构
    • 1.4 koa中间件开发与使用
    • 10.1 单元测试
    • 11.1 开发debug
    • 12.1 快速启动
    • 12.2 框架设计
    • 12.3 分层操作
    • 12.4 数据库设计
    • 12.5 路由设计
    • 12.6 webpack4环境搭建
    • 12.7 使用react
    • 12.8 登录注册功能实现
    • 12.9 session登录态判断处理
    • 13.1 import export使用
    • 2.1 原生koa2实现路由
    • 2.2 koa router中间
    • 3.1 GET请求数据获取
    • 3.2 POST请求数据获取
    • 3.3 koa bodyparser中间件
    • 4.1 原生koa2实现静态资源服务器
    • 4.2 koa static中间件
    • 5.1 koa2使用cookie
    • 5.2 koa2实现session
    • 6.1 koa2加载模板引擎
    • 6.2 ejs模板引擎
    • 7.1 busboy模块
    • 7.2 上传文件简单实现
    • 7.3 异步上传图片实现
    • 8.1 mysql模块
    • 8.2 async await封装使用mysql
    • 8.3 项目建表初始化
    • 9.1 原生koa2实现JSONP
    • 9.2 koa jsonp中间件
  • 其他

    • 操作数据库
    • Session 与 Token
    • Cookie、Session、Token、JWT
    • Socket
完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

Express|Nodejs专题系列

# Express

30 秒速记

  • 核心就两件事:路由(方法 + 路径 → 处理函数)和中间件(按注册顺序串起来的函数链)
  • 取参三处:路径参数 req.params、查询串 req.query、请求体 req.body(要先挂解析中间件)
  • 宽的中间件和通配路由会吞掉后面的请求,具体的放前面,兜底的放最后
  • 外部输入一律当字符串看,进业务前做校验和类型转换
  • Express 4 里 async 处理器抛错不会自动进错误处理,Express 5 才会

Express 就是一个轻量的路由加中间件框架,理解了「按注册顺序过一条函数链」,大部分问题都能推出来。 比如为什么 404 兜底要写最后、为什么跨域中间件要写最前、为什么 req.body 是 undefined(解析中间件没挂或挂晚了)。取参记住三个位置就够了:req.params、req.query、req.body,它们全是客户端给的,?id=abc 进来就是字符串 'abc',不校验就直接查库迟早出事。版本上要留意,Express 5 才会把 async 函数里的异常自动交给错误处理,4 里要自己 try/catch 再 next(err)。

理解「Express」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 middleware 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

Express 的设计非常薄,核心只有三样东西:app、中间件、路由。app 本身就是一个函数,签名是 (req, res),所以可以直接丢给 http.createServer(app)。中间件是 (req, res, next) => {} 形式的函数,app.use() 和 app.get() 这类方法都是往内部的一个数组里追加「层」,请求进来就从头到尾挨个匹配。

const express = require('express')
const app = express()

app.use((req, res, next) => {          // 1. 所有请求都先经过这里
  console.log(req.method, req.url)
  next()                               // 不调就会挂住
})

app.use(express.json())                // 2. 解析 JSON 请求体,之后 req.body 才有值

app.get('/users/:id', (req, res) => {  // 3. 只处理 GET /users/xxx
  res.json({ id: req.params.id, tab: req.query.tab })
})

app.use((req, res) => res.status(404).json({ msg: 'Not Found' }))   // 4. 兜底
app.use((err, req, res, next) => res.status(500).json({ msg: err.message })) // 5. 错误处理

app.listen(3000)
// GET /users/7?tab=post → {"id":"7","tab":"post"},注意 id 是字符串 "7"
@前端进阶之旅: 代码已经复制到剪贴板

这段代码基本覆盖了日常 Express 的全部骨架。顺序有讲究:日志在最前面才能记到所有请求;express.json() 要在用到 req.body 的路由之前;404 必须在所有路由之后,否则会把正常请求截走;错误处理放最后,而且必须写满四个参数。

Express 4.16 起,express.json() 和 express.urlencoded() 已经内置,不用再单独装 body-parser。Express 5 在 2024 年正式发布,主要变化是 async 处理器的异常会自动交给错误处理、路由路径语法更严格、移除了 res.send(200) 这类老签名,老项目升级前要过一遍迁移说明。

面试官追问

追问 1Express 4 里 async 路由查库抛错,请求直接挂住,为什么?
参考回答

Express 4 不认识 Promise,async 函数里抛的错变成了未处理的 rejection,没人调 next(err)。要么每个处理器 try/catch 后 next(err),要么用 express-async-errors 打补丁,要么升到 Express 5,它会自动把 rejected 的 Promise 交给错误处理。

追问 2/users/:id 和 /users/me 两个路由,访问 /users/me 进了第一个,怎么办?
参考回答

:id 能匹配任何一段,先注册就先命中,req.params.id 变成 'me'。把 /users/me 写在前面,或者给参数加约束;Express 4 可以写 /users/:id(\\d+),Express 5 换了路由语法,不再支持这种正则写法,要在处理器里自己校验。

追问 3req.query.page 拿来直接 page * 10 算分页,有什么坑?
参考回答

它是字符串,'2' * 10 恰好能隐式转成 20,但 '2' + 1 就是 '21',?page=abc 会算出 NaN,?page[]=1 甚至会变成数组。进业务前统一转换:const page = Math.max(1, Number.parseInt(req.query.page, 10) || 1),复杂的用 zod 一类的 schema 校验。

追问 4一个请求进来,Express 内部大概是怎么走的?
参考回答

app 收到请求后遍历内部的 stack,按顺序拿每一层去匹配路径和方法,匹配上就调用,调用里的 next() 就是「接着往后找下一层」。传了错误就跳过普通层,只找四参数的错误处理层,全部找完都没人响应就走默认的 404。

# Express 基础应用

30 秒速记

  • Express 是第三方包,要 npm install express 并写进 package.json,不是 Node.js 自带的
  • 定位类似前端的 jQuery:把原生 http 模块包一层,让写服务端更省事
  • 原生要自己解析 URL、拼响应头、判断方法;Express 给了路由、中间件、res.send / res.json
  • 它很「薄」,不管目录结构、不带 ORM,大项目常在它上面再搭一层或换 NestJS / Egg

Express 是 Node.js 生态里最老牌的 Web 框架,作用就像 jQuery 之于 DOM:底层能力还是 http 模块,它只是让常见操作变短。 用原生写一个带两个路由的服务,你得自己 if (req.url === ...)、自己设 Content-Type、自己 JSON.stringify;换成 Express,app.get('/', ...) 加 res.json(obj) 两行就完了。它的优点是简单、生态大,缺点也是太简单,项目结构、参数校验、依赖注入都得自己定,所以团队项目里我会先约定好目录和中间件,不然很快就乱。

Express 是一个第三方模块,对原生模块封装了一套更灵活、更简洁的应用框架,其在 Node.js 环境的地位和作用好比 jQuery 在前端的地位和作用。

理解「Express 基础应用」时,要先明确输入、运行阶段和可观察输出。这里的交互实验会分别执行正常路径与失败路径,并把 Node.js 的关键状态变化和同屏代码对应起来;不能只记命令名称。

工程中还要验证退出码、资源清理和异常输入。属于 middleware 场景的配置应保持最小可复现,并在开发环境与 CI 中使用相同命令复跑,避免把平台差异或隐式默认值带到线上。

面试官追问

追问 1新人说 Express 是 Node.js 内置的,就没写进 package.json,有什么问题?
参考回答

Express 是第三方包,没声明依赖,换台机器或者 CI 里 npm ci 一跑,启动就报 Cannot find module 'express'。他本机能跑,多半是上级目录或全局恰好装过。依赖必须写进 dependencies。

追问 2原生 http 写一个返回 JSON 的接口,和 Express 比差在哪?
参考回答

原生要写 res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify(data)),路由靠 if 判断 req.url 和 req.method。Express 一句 res.json(data) 搞定,路由、查询串解析、404 都有现成的。

追问 3CI 报找不到 express,同事说全局装一下就好,你同意吗?
参考回答

不同意。require 默认不会去全局目录找包,全局装了也不一定能解决,就算碰巧好了也是把环境差异藏起来了。正确做法是把它写进项目依赖,提交 lock 文件,CI 用 npm ci 装。

追问 4新项目还会选 Express 吗?
参考回答

看规模。小服务、BFF、脚本型接口用 Express 足够,资料多上手快。团队大、要强约定和分层,就考虑 NestJS;追求性能和 schema 校验一体化,可以看 Fastify。

# 路由

30 秒速记

  • 路由 = 把「请求方法 + URL 路径」映射到一个处理函数
  • 服务端能拿到的是路径和查询串;#hash 锚点不会发给服务器,只在前端路由里有用
  • 资源定位放路径 /orders/42,筛选条件放查询串 ?status=paid&page=2
  • Express 路由默认不区分大小写、不严格区分尾斜杠,可以通过 app.set 改
  • 路由多了用 express.Router() 按模块拆,再 app.use('/api/users', userRouter) 挂上去

路由就是一张对照表:什么方法、什么路径的请求,交给哪个函数处理。 在 Express 里写成 app.get('/users/:id', handler),:id 是动态段,取出来放在 req.params 里。要说清楚的一点是,URL 里的锚点 #xxx 浏览器根本不会发给服务器,所以服务端路由只看路径和查询串,靠锚点切换内容那是前端路由的事。实际项目里路由一多,我会按资源拆成多个 Router 文件,入口只负责挂载。

← 1.1 Express概览篇1.0 koa2概览篇 →

fe