Web 全栈知识体系 / Full-Stack Web Development Knowledge System
Web 大区按照一次请求的完整生命周期组织,而不是按照零散框架名称堆叠。
框架会变化,请求跨越的边界却相对稳定:浏览器收集输入并管理本地状态,网络协议传输有明确语义的数据,服务端执行认证和业务规则,存储系统保证所需的一致性,部署平台负责把版本安全地交付给用户。理解这些边界后,React、Vue、Next.js、Nuxt 或某个 ORM 才是可替换的实现,而不是知识体系本身。
JavaScript / TypeScript
↓
浏览器、HTTP 与 Web API
↓
React / Next.js 或 Vue / Nuxt
↓
Node.js 与后端框架
↓
数据库、ORM、Redis、MQ 与搜索
↓
认证、安全、分布式系统
↓
测试、可观测性、CI/CD 与部署1. 浏览器中的执行边界
浏览器同时承担文档解析、脚本执行、样式计算、布局、绘制、网络和安全隔离。 页面变慢不一定是框架问题,也可能来自资源、主线程任务或渲染阶段。
HTML / CSS / JavaScript
-> Parse and build DOM / CSSOM
-> Style calculation
-> Layout
-> Paint
-> CompositeJavaScript 通常在主线程执行。 长任务会阻塞输入、动画和页面更新。
优化交互时关注:
- 输入事件到处理开始的等待;
- 处理函数自身耗时;
- 状态更新触发的渲染;
- Layout 和 Paint 范围;
- 图片、字体和第三方脚本;
- 主线程之外是否可以使用 Worker;
- 取消和过期异步结果。
框架帮助组织组件,不会自动消除浏览器执行成本。
2. HTTP 请求由多层协议组成
用户输入 URL 后,浏览器可能经历:
URL parsing
-> DNS resolution
-> TCP or QUIC connection
-> TLS handshake
-> HTTP request
-> CDN / proxy / gateway
-> application route
-> response streaming
-> browser cache and rendering每一层都有独立缓存、超时和错误。 “接口失败”不足以定位问题。
请求需要明确:
- 方法与资源语义;
- 路径和查询参数;
- Header 与 Cookie;
- Body 编码和大小;
- 身份与权限;
- 幂等性;
- 超时和取消;
- 缓存策略;
- 错误响应格式。
GET 应用于读取资源,不能把有副作用操作隐藏在可缓存链接中。 重试 POST 前要确认业务是否有幂等键。
3. 前端状态分为不同来源
不是所有状态都应该放进同一个全局 Store。
常见分类包括:
- URL 状态:页面、筛选、搜索和可分享位置;
- 服务端状态:查询结果、加载、错误和缓存;
- 表单状态:输入、校验和提交;
- 本地 UI 状态:展开、选中和临时弹窗;
- 会话状态:当前身份和权限摘要;
- 持久化偏好:主题、语言和布局。
服务端数据有自己的新鲜度和失效规则。 把它复制进多个 Store,会产生互相冲突的真相来源。
URL 中适合保存可导航状态,使刷新、后退和分享保持一致。 敏感信息不能进入 URL,因为它可能出现在历史、日志和 Referer 中。
4. 渲染策略是数据与缓存决策
现代框架可能支持 CSR、SSR、SSG 和增量生成。 选择依据不是名称流行度,而是数据何时可用、是否个性化和能否缓存。
| 模式 | 优势 | 主要代价 |
|---|---|---|
| CSR | 交互灵活 | 首屏依赖脚本和 API |
| SSR | 首次响应包含内容 | 服务端计算与缓存复杂 |
| SSG | CDN 直接分发 | 内容更新需要重建 |
| 增量生成 | 平衡更新与缓存 | 失效和一致性更复杂 |
身份相关页面不能把一个用户的响应缓存给其他用户。 缓存键必须包含影响响应的所有维度,或明确禁止共享缓存。
Hydration 需要服务端和客户端初始树一致。 时间、随机数和仅浏览器可见状态可能造成不一致。
5. Node.js 的并发模型
Node.js 使用事件循环组织大量 I/O,但 JavaScript 回调仍可能阻塞事件线程。
incoming request
-> event loop callback
-> async I/O submitted
-> event loop serves other work
-> completion callback
-> response异步不等于自动并行。 CPU 密集计算会占用事件线程,需要 Worker、独立进程或外部计算服务。
Promise 错误必须在明确边界捕获。 只打印错误而继续返回成功,会制造难以诊断的半失败状态。
服务端还需要限制:
- 请求体大小;
- 并发与队列;
- 数据库连接;
- 外部调用超时;
- 重试预算;
- 文件和临时资源;
- 优雅关闭时间。
6. API 边界必须运行时校验
TypeScript 类型不会随 JSON 传输。 服务端和客户端都要把外部数据视为不可信。
request bytes
-> parse
-> schema validation
-> authorization
-> domain command
-> transaction
-> response schema校验包括类型、长度、范围、枚举和跨字段关系。 权限检查必须针对具体资源,而不是只确认用户已经登录。
错误响应使用稳定机器码和安全的人类说明。 内部堆栈、SQL、路径和密钥不能返回给客户端。
7. 数据库与事务
关系数据库适合需要约束、事务和多维查询的核心业务数据。 键值、文档、搜索和时序系统针对不同访问模式优化,不能只按数据长相选型。
选型前先写出:
- 主键和实体边界;
- 读写比例;
- 查询条件和排序;
- 一致性要求;
- 数据规模和增长;
- 保留期限;
- 备份与恢复目标;
- 多租户隔离;
- 迁移和回滚。
事务应围绕业务不变量。 多个 SQL 成功不代表业务正确,约束、隔离级别和并发冲突都要设计。
ORM 提高开发效率,但不能替代理解索引、查询计划和连接池。 生成的查询仍需在真实数据规模上检查。
8. 缓存和消息队列
缓存减少重复计算和下游访问,但会引入失效与一致性问题。
read request
-> cache hit -> return
-> cache miss -> load source -> populate -> return需要定义缓存键、TTL、容量、淘汰、穿透保护和更新策略。 缓存不可用时系统应降级,而不是瞬间把全部流量压向数据库。
消息队列把生产和消费解耦。 它不会自动提供“恰好一次”的业务结果。
消费者需要幂等处理、重试上限、死信、顺序边界和可观察积压。 生产成功但事务回滚,或事务成功但消息未发出,都需要 Outbox 等一致性方案。
9. 身份、安全和浏览器防护
认证回答用户是谁,授权回答用户能操作什么资源。 隐藏按钮不是授权,权限必须在服务端执行。
Web 安全至少覆盖:
- SQL/命令/模板注入;
- XSS 与输出编码;
- CSRF 与 Cookie 策略;
- SSRF 与出站网络限制;
- 文件上传类型、大小和存储;
- 开放重定向;
- 密钥和环境变量;
- 登录限速和会话失效;
- 依赖供应链;
- 安全 Header。
所有外部 URL、富文本和文件都应被视为不可信数据。
10. 可观测性
日志、指标和 Trace 分别回答不同问题。
- 日志保存离散事件与上下文;
- 指标展示趋势、容量和报警;
- Trace 连接跨服务请求阶段。
请求入口生成或接收关联 ID,并传递给数据库、消息和外部服务。 日志应结构化,不能记录密码、Token、Cookie 和敏感正文。
关键 SLI 包括成功率、延迟分位数、吞吐、队列和资源饱和度。 报警应指向用户影响和可执行处置,而不是为每个瞬时指标制造噪声。
11. 测试策略
Web 系统需要多层测试:
- 单元测试验证纯函数和领域规则;
- 组件测试验证 UI 状态与交互;
- 集成测试验证数据库、缓存和消息;
- 契约测试验证 API Schema;
- 端到端测试验证关键用户路径;
- 安全测试验证权限和不可信输入;
- 性能测试验证容量与尾延迟;
- 部署测试验证迁移、健康检查和回滚。
测试数据应稳定可复现,并清理自己创建的资源。 只测试正常路径会把大量生产故障留到用户发现。
12. 部署与回滚
构建产物必须可追溯到源码提交和依赖锁文件。 环境差异通过配置注入,密钥不进入镜像和仓库。
commit
-> test and build
-> immutable artifact
-> preview / staging verification
-> progressive production rollout
-> health and SLI observation
-> promote or rollback数据库迁移需要向前和向后兼容窗口。 先扩展 Schema,再发布读写兼容代码,最后清理旧字段,比一步删除安全。
健康检查应区分进程存活、服务可用和依赖就绪。 发布前必须实际演练回滚,而不是只保留一个按钮。
13. 学习项目验收
贯穿项目应包含公开页面、登录资源、管理员操作、事务、异步任务和部署环境。
验收时主动注入:
- 重复提交;
- 网络超时;
- 数据库冲突;
- 缓存失效;
- 无权限访问;
- 消费者重试;
- 部署回滚;
- 依赖不可用。
能够解释并恢复这些失败,才说明掌握的是全栈系统,而不只是框架正常用法。
课程目录
- JavaScript 与 TypeScript
- React 生态:React、Next.js、Redux Toolkit、Zustand
- Vue 生态:Vue、Nuxt、Pinia
- 浏览器、HTTP 与 API
- Node.js 与后端框架
- 后端工程
- 数据库与数据访问
- Redis、消息队列与中间件
- 身份认证与安全
- DevOps 与部署
推荐顺序
React 路线:JS → TS → 浏览器 → React → 状态与数据层 → Next.js。
Vue 路线:JS → TS → 浏览器 → Vue → Vue Router 与 Pinia → Nuxt。
后端路线:JS/TS → Node.js → HTTP/API → 数据库 → Redis/MQ → 认证安全 → 系统设计与部署。
全栈路线不是把两条路线简单相加,而是理解服务端与浏览器之间的序列化、缓存、权限、错误和性能边界。
一次请求的端到端路径
用户操作
-> 浏览器事件与组件状态
-> URL、Header、Cookie、Body
-> DNS / TLS / CDN / 反向代理
-> 路由、中间件、认证与参数校验
-> 领域服务与事务
-> 数据库、缓存、消息队列或外部 API
-> 状态码、响应体与缓存策略
-> 客户端解析、状态更新与界面重绘每个箭头都是故障边界。按钮无响应可能是事件处理问题,也可能是请求仍在等待;接口返回成功不代表事务已经持久化;数据库更新完成,也不代表缓存和异步消费者立即一致。排查时应保存请求标识,把浏览器网络面板、服务端日志、链路追踪和数据库状态串成同一条时间线。
必须建立的四类能力
语言能力要求理解 JavaScript 运行时、闭包、模块、异步任务和 TypeScript 类型边界。界面能力要求处理渲染、状态所有权、可访问性和错误反馈,而不仅是拼装组件。服务端能力要求掌握 HTTP 语义、输入验证、认证授权、幂等性、事务和并发。运维能力则要求能配置环境、保护密钥、观察生产系统,并在失败时回滚。
这些能力不能被代码生成替代。AI 可以快速生成 CRUD 或配置模板,但开发者仍需判断数据是否越权、重试会不会重复扣款、缓存是否允许陈旧、Promise 失败由谁捕获,以及部署版本是否真的服务了流量。
正确性、安全和性能的共同边界
前后端共享的数据结构必须在运行时校验,因为 TypeScript 类型不会随 JSON 传输。身份认证回答“用户是谁”,授权回答“此用户能否操作这个资源”;只在页面隐藏按钮不能构成权限控制。所有外部输入都应视为不可信,数据库查询、文件上传、重定向地址和富文本输出分别需要对应的防护。
性能优化同样从端到端指标开始。减少一次组件渲染未必改善用户体验,增加缓存也可能引入一致性错误。优先测量首屏、交互延迟、接口尾延迟、查询耗时和失败率,再判断瓶颈位于网络、JavaScript、服务端计算还是数据访问。
学完本区后,应能实现并解释一条完整请求链路,为失败设计明确响应,选择合适的数据与缓存策略,并把应用通过可观察、可回滚的流程部署到生产环境。
用项目验证学习结果
建议用一个持续演进的小项目贯穿学习,而不是每章重新写互不相关的示例。项目至少包含公开页面、登录用户资源、管理员操作、数据库事务、缓存或异步任务,以及预览和生产两套环境。每引入一个组件,都要写清它解决的具体问题,并保留不引入它时的简单基线。
验收项目时不要只检查页面能打开。还要模拟重复提交、网络超时、数据库冲突、缓存失效、无权限访问和部署回滚;确认用户获得可理解的反馈,服务端留下可关联的诊断信息,失败不会产生半完成状态。能够解释这些失败路径,才说明掌握了全栈系统,而不只是记住框架的正常用法。