前端本地开发构建和更新的过程

文章目录

    • 一、开发环境启动时发生了什么?
      • [1. Node 进程启动](#1. Node 进程启动)
      • [2. 依赖预构建(仅 Vite)](#2. 依赖预构建(仅 Vite))
      • [3. 启动本地服务](#3. 启动本地服务)
    • 二、浏览器请求资源时发生了什么?
      • [1. HTML 响应](#1. HTML 响应)
      • [2. 模块请求](#2. 模块请求)
      • [3. 依赖加载](#3. 依赖加载)
    • [三、更新代码时发生了什么?(HMR 流程)](#三、更新代码时发生了什么?(HMR 流程))
      • [1. 文件系统监听](#1. 文件系统监听)
      • [2. 增量编译](#2. 增量编译)
      • [3. HMR 消息推送](#3. HMR 消息推送)
      • [4. 浏览器执行模块热替换](#4. 浏览器执行模块热替换)
    • 四、生产构建时的不同点
    • [五、与 webpack 对比](#五、与 webpack 对比)
    • 六、流程图

一、开发环境启动时发生了什么?

当你运行 npm run dev 的时候,本质上经历了以下几个阶段:

1. Node 进程启动

  • Vite/webpack 的 CLI 命令启动一个 Node 进程。
  • Node 读取 vite.config.jswebpack.config.js 配置。
  • 创建一个 Dev Server (底层一般用 http + koa/express)。

2. 依赖预构建(仅 Vite)

  • Vite 会用 esbuildnode_modules 里的依赖(react、react-dom、lodash...)快速预编译成 ESM 格式。

  • 为什么要预构建?

    • node_modules 里通常是 CommonJS,浏览器不能直接跑。
    • 避免浏览器发太多 import 请求,合并成少量 bundle。
  • 结果会缓存到 node_modules/.vite/

3. 启动本地服务

  • 服务监听在 http://localhost:5173(端口可配)。

  • 提供:

    • 静态文件服务(HTML、图片、字体)。
    • 模块转换服务(JSX/TS → JS)。
    • HMR WebSocket 服务(实时更新通知)。

二、浏览器请求资源时发生了什么?

当你打开 http://localhost:5173

1. HTML 响应

  • 浏览器先请求 /index.html

  • Dev Server 拦截并可能注入一些运行时代码(如 HMR 脚本)。

  • 浏览器解析到:

    html 复制代码
    <script type="module" src="/src/main.jsx"></script>

2. 模块请求

  • 浏览器会去请求 /src/main.jsx

  • Dev Server 发现这是源码文件 → 走插件链处理:

    • 解析 JSX → React.createElement
    • 如果是 TS → 去掉类型注解
    • 替换 import.meta.env → 注入环境变量
  • 返回一个浏览器能执行的 ESM 脚本。

例如你写的:

jsx 复制代码
import React from "react";
const App = () => <h1>Hello</h1>;
export default App;

Vite 转换后可能变成:

js 复制代码
import React from "/node_modules/.vite/deps/react.js";
const App = () => React.createElement("h1", null, "Hello");
export default App;

3. 依赖加载

  • 如果脚本里有 import React from 'react',浏览器会发请求 /node_modules/.vite/deps/react.js
  • 这个文件是 Vite 预构建好的,直接返回。

这样,整个应用就在浏览器里运行起来了。

三、更新代码时发生了什么?(HMR 流程)

当你修改 App.jsx 里的内容,比如:

jsx 复制代码
<h1>Hello</h1> → <h1>Hello World!</h1>

会发生:

1. 文件系统监听

  • Dev Server 内部用 chokidar 监听文件变动。
  • 一旦 App.jsx 变了 → 触发编译。

2. 增量编译

  • Vite 用 esbuild 或 babel 插件只重新编译变动的文件。
  • 不会重新打整个包(这是 webpack 慢的原因)。

3. HMR 消息推送

  • Dev Server 通过 WebSocket 向浏览器发送消息:

    json 复制代码
    { "type": "update", "path": "/src/App.jsx" }

4. 浏览器执行模块热替换

  • 浏览器的 Vite runtime 收到消息。

  • 它会请求 /src/App.jsx 最新编译结果。

  • 只替换该模块,并触发 React Fast Refresh:

    • UI 会更新
    • 组件 state 不会丢失

四、生产构建时的不同点

运行:

bash 复制代码
npm run build

流程和开发完全不同:

  1. 全量打包

    • Vite 内部调用 Rollup,把所有模块打成 bundle。
    • 生成 hash 文件名(app.abc123.js),防止缓存污染。
  2. 代码优化

    • Tree-shaking(移除没用的代码)。
    • Scope hoisting(减少闭包层级)。
    • 压缩(Terser/Esbuild)。
  3. 产物输出

    • dist/ 目录:

      复制代码
      dist/
      ├── index.html
      ├── assets/
      │   ├── index-xxxx.js
      │   ├── vendor-xxxx.js
      │   └── style-xxxx.css

五、与 webpack 对比

特性 Vite webpack
开发启动 秒级(原生 ESM + esbuild) 慢(需要先打 bundle)
更新速度 增量更新,几乎秒级 HMR 需要 rebuild,慢
依赖处理 esbuild 预构建 babel/ts-loader 全量编译
打包器 Rollup webpack 本身
插件生态 新但增长快 成熟,功能强大

六、流程图

成功
失败
开发者保存文件
文件监听器检测到变化
构建工具增量编译
Vite: 按需编译
Webpack: 快速重建
开发服务器通过 WebSocket 推送更新
浏览器 HMR 运行时接收更新
执行 HMR
替换模块, 保持状态, UI 无刷新更新
进行整页重载


👉点击进入 我的网站

相关推荐
崔庆才丨静觅13 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606114 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了14 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅14 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅14 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅15 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment15 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅15 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊15 小时前
jwt介绍
前端
爱敲代码的小鱼15 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax