Vite-浏览器如何处理 Esm 模块
“浏览器如何处理 ESM 模块” 其实浏览器处理 Vite 提供的 ESM 模块核心就是遵循原生 ESM 规范“按需请求、逐个加载”整个过程和 Vite 的“不打包”逻辑完美配合具体流程拆解如下下面用一张流程图直观展示浏览器从加载入口 HTML 到最终执行渲染的完整链路flowchart TD A[浏览器加载 index.html] -- B[识别 script typemodule] B -- C[解析 main.jsx 的 import 语句] C -- D[递归发起 HTTP 请求依赖] D -- E{Vite 按需编译} E -- F[React 组件: esbuild 编译 JSX/TSX] E -- G[第三方依赖: 预构建 CJS 转 ESM] E -- H[普通 JS/CSS: 直接返回] F -- I[浏览器递归加载所有依赖] G -- I H -- I I -- J[从入口模块执行并渲染] J -- K[WebSocket 热更新通知] K -- L[浏览器重新请求更新模块] L -- M[局部渲染, 不刷新页面]这张图把「浏览器原生行为」和「Vite 的翻译工作」分成了上下两层上半部分是浏览器按 ESM 规范做的加载动作下半部分是 Vite 针对不同模块类型做的编译处理最后通过 WebSocket 实现精准的热更新。1. 第一步浏览器加载入口 HTML触发 ESM 启动Vite 开发服务器启动后你访问 localhost:5173 时浏览器首先加载的是项目根目录的 index.html。这个 HTML 里会有一个关键的脚本标签!-- Vite 自动注入的入口脚本typemodule 是核心 --script typemodule src/src/main.jsx/script• typemodule 是浏览器原生支持 ESM 的标识告诉浏览器“这个脚本是一个 ESM 模块需要按模块化规则加载”。2. 第二步浏览器解析入口模块递归请求依赖当浏览器解析 main.jsxReact 入口文件时会遇到 import 语句比如导入 React 组件、工具函数等例如// main.jsx 中的导入import React from react;import ReactDOM from react-dom/client;import App from ./App.jsx; // 自定义 React 组件此时浏览器会做两件事1. 识别依赖通过 import 语句明确当前模块依赖了 react、react-dom、./App.jsx 三个模块2. 发起请求针对每个依赖自动向 Vite 开发服务器发起 HTTP 请求获取对应的 ESM 模块文件比如◦ 请求 http://localhost:5173/node_modules/react/index.js第三方依赖◦ 请求 http://localhost:5173/src/App.jsx自定义组件3. 第三步Vite 按需编译模块返回给浏览器浏览器的请求到达 Vite 服务器后Vite 会根据“请求的模块类型”做针对性处理• 如果是 React 组件.jsx/.tsxVite 会用 vitejs/plugin-react esbuild 快速编译——把 JSX 语法如 App /转译为 React.createElement(App)同时处理 TS 语法如果是 TSX然后把“编译后的 JS 代码”以 ESM 格式返回给浏览器• 如果是第三方依赖如 reactVite 会先对依赖做“预构建”启动时一次性完成把 CommonJS 格式的依赖很多 npm 包还是 CommonJS转译为 ESM 格式再返回给浏览器• 如果是普通 JS/CSS直接返回原生内容或简单处理后返回。4. 第四步浏览器递归加载所有依赖最终执行浏览器拿到 Vite 返回的“编译后 ESM 模块”后会重复第二步解析这个模块里的 import 语句继续请求它的依赖比如 App.jsx 可能导入了 ./Button.jsx浏览器就再请求 Button.jsx。直到所有依赖模块都加载完成后浏览器会从入口模块main.jsx开始执行代码最终渲染 React 应用// main.jsx 执行逻辑const root ReactDOM.createRoot(document.getElementById(root));root.render(App /); // 执行渲染5. 当模块更新时热更新浏览器如何处理这一步就对应 Vite 热更新的核心1. 你修改了某个组件如 Button.jsxVite 会重新编译这个单个模块然后通过 WebSocket 告诉浏览器“/src/Button.jsx 模块更新了”2. 浏览器收到通知后只需要重新请求“更新后的 Button.jsx 模块”无需请求其他无关模块3. 浏览器用新模块替换旧模块React 会感知到组件变化只重新渲染 Button 组件及其父组件局部渲染不刷新页面。简单总结浏览器处理逻辑的核心浏览器其实只做了它“原生就会做的事”——识别 typemodule 脚本按 import 语句递归请求模块并执行。而 Vite 的作用是“在中间做了层高效的‘翻译官’”把 React 特有的语法JSX/TSX、非 ESM 依赖实时转译为浏览器能懂的 ESM 模块同时精准控制更新范围让整个过程又快又轻量。1. CommonJS 与 ESM 的核心区别在深入 Vite 的模块处理机制之前先厘清 JavaScript 模块体系中最常被问到的两个概念CommonJSCJS和 ES ModuleESM。它们代表了两种不同的模块规范理解它们的差异是理解 Vite 预构建、按需编译等行为的前提。CommonJSCJS由 Node.js 社区提出并广泛使用采用require()加载模块、module.exports导出模块。它是同步加载模块在运行时被解析适合服务端场景。ES ModuleESM是 ECMAScript 官方标准采用import导入、export导出。它是静态分析、异步加载浏览器原生支持适合前端场景。两者核心差异对比如下对比维度CommonJSCJSES ModuleESM加载方式同步加载运行时解析异步加载静态分析导入语法require(module)import xxx from module导出语法module.exports xxxexport default xxx/export { xxx }执行时机运行时执行动态编译时静态解析可静态分析依赖浏览器支持不支持需打包器转换原生支持typemodule循环依赖处理容易出问题部分导出可能为 undefined设计上更健壮支持 live bindingTree Shaking不支持难以静态分析天然支持可静态分析未使用导出这也是为什么 Vite 在开发模式下需要做「预构建」很多 npm 包仍然以 CommonJS 格式发布而浏览器只认 ESM所以 Vite 必须先把这些 CJS 依赖转译为 ESM 格式浏览器才能直接加载。2.问题 React.createElement不是react 得用法吗因为经过 Vite esbuild 的处理后最终给到浏览器的已经不是“带 JSX 的 React 源码”而是纯原生 JavaScript 代码——浏览器识别的是这份“转换后的 JS 代码”而非原始 React 代码核心逻辑分两步1. React 代码被“转译为原生 JS 语法”浏览器不认识的是 React 特有的 JSX 语法如 div /但经过 esbuild 转译后• JSX 会变成 React.createElement(...) 这种原生 JS 函数调用函数调用是浏览器完全能识别的 JS 基础语法• 若有 ES6 语法箭头函数、let/const 等会被降级为 ES5 语法如 var、普通函数适配所有浏览器。例如原始 React 代码// 浏览器不认识的 React 代码含 JSXconst Button () buttonClick/button;转译后给到浏览器的代码// 浏览器能直接识别的原生 JSimport { createElement } from react; // 依赖引用也是原生 ESM 语法const Button () createElement(button, null, Click);2. React.createElement 有“具体的 JS 实现”React.createElement 看似是 React 专属函数但它本质是 react 库导出的一个普通 JS 函数——Vite 会把 react 库本身也处理成浏览器能识别的 ESM 模块其中就包含这个函数的实现。比如浏览器请求 react 模块时Vite 返回的代码里会有类似这样的逻辑简化版// react 模块的核心实现简化export function createElement(type, props, ...children) {// 本质是返回一个“描述 DOM 结构的对象”React 元素return {$$typeof: Symbol.for(react.element),type,props: { ...props, children },// 其他内部属性...};}当浏览器执行 createElement(button) 时其实就是在调用这个“普通 JS 函数”生成一个描述按钮的“React 元素对象”——而这个对象最终会被 react-dom 库同样是 JS 实现转换成真实的 DOM 节点渲染到页面上。核心总结浏览器能识别的关键是 Vite esbuild 做了“翻译和搭桥”• 把“浏览器不认识的 React 语法JSX”翻译成“浏览器认识的 JS 函数调用”• 把“React 库的函数如 createElement”提供成“浏览器能加载的 JS 模块”。最终浏览器执行的全是原生 JS 代码自然就能识别并运行 React 应用了。

相关新闻

V2PE位置编码方案v0到v6全对比:小步长RoPE位置ID的7种设计演进

V2PE位置编码方案v0到v6全对比:小步长RoPE位置ID的7种设计演进

【免费下载链接】V2PE 项目地址: https://ai.gitcode.com/OpenGVLab/V2PE 点击查看 免费下载 V2PE(Variable Visual Position Encoding)是一种面向视觉语言模型的"可变小步长"位置编码方案,它通过给图像 token 分配远小…

2026/10/17 1:51:28 阅读更多 →
机考算法复盘:扑克牌最小打出次数与钢琴旋律拼接递增序列

机考算法复盘:扑克牌最小打出次数与钢琴旋律拼接递增序列

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 1:51:28 阅读更多 →
5分钟快速上手DeepSeek-V3.2-4layers:ModelScope下载与首次推理完整教程

5分钟快速上手DeepSeek-V3.2-4layers:ModelScope下载与首次推理完整教程

【免费下载链接】DeepSeek-V3.2-4layers 项目地址: https://ai.gitcode.com/hf_mirrors/vllm-ascend/DeepSeek-V3.2-4layers 点击查看 免费下载 本教程带你 5 分钟快速上手 DeepSeek-V3.2-4layers 模型:通过 ModelScope 下载 模型文件,安装 …

2026/10/17 1:51:28 阅读更多 →

最新新闻

PDMS-AVEVA-E3D二次开发教程(18):批量化作业与无人值守——任务清单、幂等、日志与失败隔离

PDMS-AVEVA-E3D二次开发教程(18):批量化作业与无人值守——任务清单、幂等、日志与失败隔离

版本声明 本篇基线为 AVEVA E3D Design 3.1,涉及前代 AVEVA PDMS 处显式标注。PML Add-in 机制的小节标题(Defining a PML Add-in、PML Application Control Object、Create a PLOBJ Control File、Create a UIC File、How to Add a PML Add-in to the P…

2026/10/17 2:33:37 阅读更多 →
PDMS-AVEVA-E3D二次开发教程(19):PDMS 到 E3D 的定制迁移——三类资产、代际差异与自查脚本

PDMS-AVEVA-E3D二次开发教程(19):PDMS 到 E3D 的定制迁移——三类资产、代际差异与自查脚本

版本声明 本篇基线为 AVEVA E3D Design 3.1;前代产品统一写作 AVEVA PDMS。政策事实:自 2024 年 4 月 1 日起,AVEVA PDMS 不再销售、不再提供支持,研发投入全部转向 E3D Design。迁移路径包括本地或云端部署,也可作为 …

2026/10/17 2:33:37 阅读更多 →
AI Agent 新利器:用 linear-cli Skill 让 Claude Code 在终端自动创建 Issue 与更新状态

AI Agent 新利器:用 linear-cli Skill 让 Claude Code 在终端自动创建 Issue 与更新状态

【免费下载链接】linear-cli linear without leaving the command line: list, start, and create PRs for linear issues. agent friendly. 项目地址: https://gitcode.com/gh_mirrors/lin/linear-cli 点击查看 免费下载 如果你正在用 Claude Code 等 AI Agent 写…

2026/10/17 2:33:37 阅读更多 →
Dubbo+Zookeeper实战:从零搭建分布式服务调用链路

Dubbo+Zookeeper实战:从零搭建分布式服务调用链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 2:33:37 阅读更多 →
最大似然位同步算法解析:从原理到FPGA工程实现

最大似然位同步算法解析:从原理到FPGA工程实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 2:33:37 阅读更多 →
Python+Selenium实现OA自动打卡:开发踩坑与运维复盘

Python+Selenium实现OA自动打卡:开发踩坑与运维复盘

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 2:32:37 阅读更多 →

日新闻

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

DeepSeek选型与部署:V3/R1、Ollama、API全攻略

简介:《DeepSeek使用方法.pdf》是一份面向DeepSeek入门及进阶用户的完整使用指南,重点围绕V3与R1两款模型的能力差异与适用场景展开,帮助读者根据任务类型与成本选择合适的模型。资源共1个PDF文件,压缩包大小约311KB,篇…

2026/10/17 0:00:25 阅读更多 →
200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

200+Deepseek润色指令拆解:从底层原理到场景落地的完整指南

简介:这是一份聚焦DeepSeek提示词优化的《200Deepseek润色指令》PDF文档,共收录两百余条可直接套用的润色指令,涵盖语法修正、风格统一、逻辑梳理、表达精炼等维度,并针对商务写作、学术论文、广告文案等场景给出差异化建议。文档…

2026/10/17 0:00:25 阅读更多 →
OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

OpenCV轮廓法物体计数系统:轻量、可控、可落地的工业级实现

简介:本资源是一份基于OpenCV的本科课程设计完整报告,面向计算机视觉初学者、图像处理学习者及高校通信/信息类专业学生,解决物体智能计数与检测结果结构化记录的实际问题。项目覆盖图像预处理、轮廓检测、边界框绘制、轨迹栏交互式参数调节、…

2026/10/17 0:00:25 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/16 21:35:51 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/17 1:44:59 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/16 15:04:24 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 21:54:38 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 14:23:36 阅读更多 →