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

文章目录

    • 一、开发环境启动时发生了什么?
      • [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 无刷新更新
进行整页重载


👉点击进入 我的网站

相关推荐
lv__pf10 小时前
Spring配置类解析 【TL spring 11】
java·前端·spring
AI分享猿10 小时前
UI设计Prompt系列(十三):响应式布局需求怎么写——让设计Prompt更接近前端实现
前端
ClouGence10 小时前
Selenium 写不动了?这个工具录一次就能跑 Web 自动化
前端·selenium·测试
hunterandroid10 小时前
[鸿蒙从零到一] HarmonyOS 地图、定位与传感器能力实战:从位置获取到运动感知
前端
大锅盖110 小时前
Web 工单要调用相机,第一步不是打开取景框,而是建立能力门禁
前端·数码相机·harmonyos
fthux10 小时前
不必下载整个仓库:GitZip Pro 让 GitHub 文件与文件夹批量下载更简单
前端·chrome·ai·edge·开源·github·firefox
奥莱维10 小时前
【无标题】
java·前端·javascript
用户9210802628610 小时前
0. 为什么我们的项目选择 Cesium:从三维地图、离线部署到工程代价
前端
阿懂在掘金11 小时前
同一份弹窗我重构了三次:从 v-model 地狱到路由式调用,终于治好了模板臃肿
前端·vue.js·前端框架
悟空瞎说11 小时前
从 CRA 到 Vite:含 Cesium 的真实项目迁移实战记录
前端