前九章是「写页面」,这一章是「做产品」:多人协作要版本管理,依赖几十个包要 npm,几百个模块要打包,上线要构建部署,风格统一要规范工具。本章按「依赖 → 打包 → 部署 → 规范」走完前端工程的完整链路,这也是本站自己(Next.js + npm)每天都在用的链路。
npm install # 按 package.json + lock 文件装全依赖
npm install vue # 新增运行时依赖
npm run dev # 执行 scripts 里定义的命令
package.json 是项目的身份证:dependencies(运行时要用的)与 devDependencies(只在构建/开发时用的,如 vite、ESLint)分册登记;版本号 ^3.4.0 是 semver 范围(允许 3.x 内升级),~ 只许补丁,写死版本是纪律。lock 文件必须提交:它锁定整棵依赖树的精确版本,保证「我的机器能跑」变成「所有人的机器都一样地跑」(没有 lock,团队各装各的,bug 复现变成玄学)。
包管理器三兄弟:npm(官方默认)、yarn、pnpm。pnpm 用硬链接 + 内容寻址把 node_modules 去重(100 个项目共享同一份 vue),磁盘和安装速度双杀,新项目我无脑推 pnpm。npm install 那句老话「删 node_modules 重装大法」之所以有效,正是因为依赖树状态复杂,lock 文件 + 统一包管理器是根治法。
浏览器只认少量文件类型,而你的源码是几百个 ESM 模块 + 各种资源,打包工具把它们编译、合并、压缩成高效的静态产物:
// vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
export default defineConfig({ plugins: [vue()] });
| webpack(上一代) | vite(现主流) | |
|---|---|---|
| 开发期 | 全量打包成 bundle 再启动 | 不打包:原生 ESM 按需加载 |
| 冷启动 | 项目大时几分钟 | 秒级 |
| 热更新 HMR | 越大越慢 | 只重编译改动的模块,毫秒级 |
| 生产构建 | 自有体系 | 底层用 Rollup |
vite 快的原因正是第 7 章的模块知识兑现:开发时浏览器原生支持 ESM,vite 只按请求「现场翻译」你正在访问的那个模块(用 esbuild,Go 写的,快一个量级),没有全量打包这一步。第 7 章说「ESM 静态分析可 tree-shaking」,这里兑现:生产构建把没用到的导出摇掉,产物小一圈。
源码 ──build──> dist/ ──部署──> 静态服务器 / CDN
npm run build 产出的 dist 是纯静态文件,关键机制是内容哈希文件名(index.9f3a2b.css):内容不变文件名不变,配合第 6 章的强缓存,浏览器「改了才重新下载」;内容变了文件名变,天然缓存失效。这个「哈希文件名 + 长缓存 + 短缓存 HTML」组合是静态资源缓存的行业答案。
部署的本质就是「把 dist 放到可访问的 URL 下」:GitHub Pages / Vercel(推代码自动部署,个人项目首选)/ 云服务器的 Nginx 静态托管(本站就是 Node 进程跑的 Next.js,稍复杂但同理)。CI/CD 是它的自动化版:push 触发流水线,自动 install → lint → build → 部署,人只管写代码。
三件套用 husky + lint-staged 挂在 git 提交钩子上,只检查本次改动文件,「不合格的代码进不了仓库」。这个「把规范自动化到提交环节」的思路,比「开会约定、靠自觉」有效一百倍。
npm create vite@latest 起一个 Vue 或 React 项目,通读 package.json 和 vite.config,辨认 dependencies/devDependencies/scripts 的每个条目。npm run build 后进 dist/,观察文件名哈希、压缩后的 JS(格式化看源码对应关系);改一行源码重 build,对比哪些文件名变了(内容寻址的实证)。