第五章:代码运行的三种状态与构建原理

序言

你听隔壁公司的一位实习生讲了个故事。他第一天上班,leader 让他在本地准备一个演示。他兴冲冲地运行了 pnpm dev,一切正常。

但当 leader 问:“这个本地演示我也能看看吗?” 实习生才发现——leader 的电脑上没有他的数据库配置,而且 Dev 模式也不适合用来演示

leader 告诉他:“本地开发用的是 Dev 模式,方便你调试。但给用户看的,应该先 pnpm build 构建出生产版本,然后部署到服务器上。”

实习生这才明白,原来代码有不同的运行环境:本地开发用 Dev,给用户看的是 Build 后部署到服务器上的版本。你听着这个故事,觉得这章得好好学学。

三种状态

随着开发的深入,老师傅特意给你科普了代码的三种生命状态,以避免你混淆。

首先是 Dev(开发模式),就是你平时用的 pnpm dev。它就像是打草稿。在这个模式下,当你修改代码并保存后,浏览器不需要刷新整个页面,只会替换改动的那一小块组件。这意味着如果你正在填写一个长长的表单,改了样式后,表单里填好的内容不会丢失。但代价是运行速度较慢,且包含了大量用于报错的调试信息。

其次是 Build(构建模式),当你准备上线时,需要运行 pnpm build。这个过程就像是把草稿排版印刷成书。它会把你写的所有 TypeScript、React 代码进行压缩、优化、翻译,最终在项目中生成一个 .next(或 dist)文件夹。这里面的代码体积极小、运行极快,是专门给用户看的正式版。

最后是 Production(生产模式),运行 pnpm start(或 next start)。这是在本地模拟正式上线的环境,用来运行刚才 build 生成的”正式版”。通常在上线前,你会用这个模式最后检查一遍有没有 Bug。

保存即生效

你可能好奇:为什么在 Dev 模式下保存文件,浏览器会自动刷新?这叫热重载(Hot Reload)

开发工具会在后台监听文件变化。一旦检测到修改,就会自动刷新浏览器或只更新改动的部分。这让你不需要每次都手动刷新,开发效率大幅提升。

而在 Build 或 Production 模式下,代码已经打包优化,没有这个监听机制,所以修改后需要重新构建。理解这个区别,你就知道为什么有时候改了代码没效果——可能是在错误的模式下运行。

package.json

这时候,你可能会疑惑:为什么输入 pnpm dev 就能启动项目? 老师傅让你打开根目录下的 package.json 文件。他告诉你,这是 Node.js 项目的核心配置文件,管理着项目的元数据、脚本和依赖。

脚本管理 (Scripts):在 scripts 字段中,定义了项目常用的运行命令。当你在终端输入 pnpm dev 时,包管理器会查表,发现它对应的是 next dev 命令并执行它。这就是为什么复杂的底层命令可以被简化成短短的 devbuild老师傅顺便提了一嘴,这里也是自定义”房间号”的地方。 还记得第一章那个烦人的端口占用吗?你完全可以在这里把命令修改为 next dev -p 4000。这样,下次你运行 pnpm dev 时,应用就会直接在 4000 端口启动,彻底避开拥挤的 3000 端口。

依赖管理 (Dependencies)dependencies 列表明确记录了项目运行所必须安装的第三方库(如 React, Next.js, Drizzle)及其具体版本号。这确保了其他人(或服务器)获取代码后,可以通过 pnpm install 安装一模一样的库,完美还原你的开发环境。

构建产物

构建完成后,你试图在文件夹里找一个 index.html 双击打开,就像第一章做的那样。老师傅告诉你构建产物在 .next(或者 dist)文件夹,但你翻遍了 .next 文件夹,只看到了一堆乱码般的 .js.json 文件。老师傅告诉你,本教程使用的 Next.js 全栈框架,本质上是一个运行在 Node.js 上的”程序”,而不是简单的”文件”。它需要连接数据库、处理 API 请求、在服务端渲染页面,这些都离不开服务器环境的支持。

当然,有些场景下你也可以开发纯静态项目(比如使用 Vite + Vue/React),这种项目打包后确实会在 dist 文件夹生成一个 index.html。但为了带你走完数据库、鉴权等完整的全栈流程,我们选择了 Next.js。不过要记住,即使是 Vite 打包出的纯静态文件,通常也不能直接双击打开。因为现代应用使用绝对路径(如 /assets/app.js)引用资源,而双击打开使用的是 文件协议file:///),这会导致浏览器找不到资源。

所以,请记住:永远不要直接双击打开构建后的代码文件,永远通过 Web 服务器(如 Next.js 的 pnpm start 或 Vite 项目的 pnpm preview)来访问你的应用。

缓存

前面说过,Dev 模式有热重载,改代码保存后浏览器会自动更新,一般不会有缓存问题。

但在 Production 模式(运行 pnpm start)或访问已部署的网站时,你可能会遇到浏览器缓存导致的怪事。比如你把按钮从蓝色改成红色,重新 pnpm build 后访问,按钮依然是蓝色的。你崩溃了,以为进入了平行宇宙。

原来,浏览器为了加载更快,把旧的 CSS/JS 文件存在了本地。你学会了三个大招:一是强制刷新(按住 Ctrl + Shift + R);二是打开浏览器无痕模式;三是打开 F12 开发者工具,在 Network 选项卡里勾选 “Disable cache”

如果强制刷新还不行,可能是构建缓存的问题,需要删除 .next 目录后重新 pnpm run build

还有一个经常被忽略的坑:修改了 .env 文件后必须重启服务(Ctrl+C 然后 npm run dev),环境变量才会生效。【详见第6章】 会详细解释为什么环境变量在进程启动时加载,运行中修改文件不会自动更新。


章节导航

- 5.1 缓存陷阱排查 (./01-缓存陷阱排查.md) 🔴
- 5.2 三种运行模式 (./02-三种运行模式.md) 🟢
- 5.3 package.json 实用指南 (./03-package.json实用指南.md) 🟢
- 5.4 构建产物与 Web 服务器 (./04-构建产物与Web服务器.md) 🟢