Vue 3 项目从代码到浏览器中间到底发生了什么这个问题我在带新人的时候被问过不下二十次。很多人敲完npm run dev看到终端里蹦出一行本地地址浏览器自动弹开页面就觉得“跑起来了收工”。可一旦页面白屏、样式错乱、热更新失灵或者打包上线后行为和本地完全两样就彻底抓瞎了。根源在于大多数人对这条链路的认知是断层的——只知道命令不知道命令背后 Vite 做了什么、浏览器又做了什么。这篇内容就是要把这条链路从头到尾拆开讲透。适合两类人看一是刚接触 Vue 3 Vite 组合、想搞清楚“为什么能跑”的新手二是已经能跑项目、但遇到构建或运行问题只能靠搜索碰运气的开发者。我会从一次dev命令的完整生命周期讲起把依赖预构建、模块解析、浏览器原生 ESM 加载、热更新、生产构建这几段关键流程逐一拆解中间穿插我自己踩过的坑和实际排查经验。读完你至少能做到看到终端输出知道它在干什么遇到白屏能定位到是哪一环断了而不是盲目删node_modules重装。1. 敲下 dev 命令之后终端里那几行字到底在忙什么很多人对 Vite 的第一印象是“快”但快在哪、快在哪个阶段说不清楚。要理解这一点得先明白传统打包工具和 Vite 在开发阶段的根本分歧。传统方案是“先打包再服务”你改一个文件它要把整个依赖图重新走一遍生成 bundle再交给浏览器。项目越大这个等待越久。Vite 走的是另一条路——开发阶段它压根不打包而是把源码当成一堆独立的 ES 模块让浏览器自己去按需请求。这个思路的转变是后面所有流程的起点。1.1 命令解析与配置加载的先后顺序npm run dev本质上是执行package.json里scripts.dev对应的命令通常是vite。这个可执行文件来自node_modules/.bin是 Vite 包安装时注册的入口。命令启动后Vite 做的第一件事不是急着起服务器而是加载配置文件。它会按顺序查找vite.config.js、vite.config.ts、vite.config.mjs等找到后解析并合并默认配置。这里有个容易被忽略的细节配置文件本身也是需要被处理的。如果写的是 TypeScript 版本Vite 会先用 esbuild 把它转成可执行的 JS再加载进来。所以你在vite.config.ts里写的import语句、类型标注运行时是被剥离过的。我见过有人在配置文件里写了依赖浏览器 API 的代码结果启动直接报错——因为配置文件是在 Node 环境里执行的不是浏览器环境。这个边界要拎清楚。配置合并完成后Vite 会确定几个关键参数root项目根目录、base公共基础路径、server.port、server.proxy等。这些参数直接决定了后续服务器怎么起、资源怎么找。比如base配错了开发时可能没事打包后所有静态资源 404这是上线翻车的经典原因之一。1.2 依赖预构建为什么第一次启动总要等一会儿配置就绪后Vite 进入一个非常关键的阶段——依赖预构建Dependency Pre-Bundling。这一步是很多人第一次启动时看到“正在优化依赖”提示的原因也是 Vite 开发体验的核心设计之一。为什么要预构建两个原因。第一兼容性。Vue 3 的生态里很多包发布的是 CommonJS 格式而浏览器原生 ESM 只认import/export。Vite 用 esbuild 把这些 CJS 包转成 ESM浏览器才能直接加载。第二性能。像lodash-es这种包内部有几百个小模块如果浏览器逐个请求光是网络往返就够呛。预构建会把它们合并成少量文件减少请求数量。预构建的产物放在node_modules/.vite/deps目录下同时生成一个_metadata.json记录缓存信息。下次启动时Vite 会对比package.json里的依赖版本和锁文件如果没变化就直接复用缓存这就是为什么第二次启动明显快很多。我遇到过预构建缓存损坏导致页面报“找不到模块”的情况处理办法很简单删掉node_modules/.vite目录重启即可不用动整个node_modules。这个技巧能省下大量重装时间。提示如果你改了vite.config.ts里的optimizeDeps配置或者手动安装了新依赖Vite 通常会自动触发重新预构建。但偶尔缓存判断会失灵手动删.vite目录是最稳妥的兜底手段。1.3 开发服务器的启动与中间件链路预构建完成后Vite 启动一个基于 Node 的 HTTP 服务器默认监听5173端口端口被占用会自动递增。这个服务器不是简单的静态文件服务它内部挂了一串中间件按顺序处理请求。理解这个中间件顺序对排查“请求为什么被拦截”“代理为什么没生效”特别有用。大致链路是这样的先经过 CORS 和基础安全头处理然后是代理中间件如果配了server.proxy接着是静态资源处理最后是核心的模块转换中间件。当浏览器请求一个.vue文件时请求会落到转换中间件上Vite 调用对应的插件比如vitejs/plugin-vue把单文件组件拆解、编译成浏览器能懂的 JS再返回。这里有个实操经验代理配置的changeOrigin和rewrite经常被写错。changeOrigin: true是把请求头的 Host 改成目标服务器的域名很多后端做了 Host 校验不设这个就会 403。而rewrite是用来去掉或替换路径前缀的比如接口实际路径没有/api前缀就得用path.replace(/^\/api/, )处理。这两个参数配错表现就是“本地请求 404 或跨域”但很多人会误以为是后端问题白白排查半天。2. 浏览器发起请求后Vite 如何把 .vue 文件变成可执行代码服务器起来了浏览器打开地址真正的“代码到浏览器”之旅才算正式开始。这一段是整个链路里信息密度最高的部分也是理解 Vite 原理的关键。浏览器拿到的第一个东西是index.html但注意这个 HTML 和传统打包工具产出的 HTML 有本质区别。2.1 index.html 作为入口的特殊地位在 Vite 项目里index.html不是放在public目录下被复制过去的静态文件而是项目的真正入口位于项目根目录。Vite 会直接把这个 HTML 作为服务器响应的起点。你在里面写的script typemodule src/src/main.js浏览器会原样解析然后发起对/src/main.js的模块请求。这个设计和传统方案完全不同。传统方案里HTML 是打包产物之一脚本路径是构建时注入的哈希文件名。而 Vite 开发阶段HTML 里的路径就是源码路径浏览器直接按这个路径请求。这也是为什么 Vite 开发时不需要“等打包”——它把模块解析的工作交给了浏览器和服务器协作完成。HTML 里还可能包含 Vite 注入的客户端脚本用于建立 WebSocket 连接、处理热更新。如果你在浏览器开发者工具的 Network 面板里看到vite/client这个请求就是它。这个脚本是热更新机制的通信基础后面会细讲。2.2 模块请求的拦截与按需编译浏览器解析main.js后发现里面有import { createApp } from vue于是发起对vue的请求。这个请求到达 Vite 服务器转换中间件识别出这是一个裸模块导入bare import会把它重写为预构建产物的路径比如/node_modules/.vite/deps/vue.js?vxxxx。这个?vxxxx是版本哈希用于缓存控制。接着main.js里可能还import App from ./App.vue浏览器请求/src/App.vue。这时vitejs/plugin-vue插件介入把单文件组件拆成三块template编译成渲染函数script原样或经处理保留style单独抽成模块。最终返回的 JS 里模板部分变成了createElementBlock之类的渲染调用样式部分通过import一个虚拟模块注入。这个“按需编译”是 Vite 快的核心。浏览器请求到哪个文件才编译哪个文件没被请求的代码完全不参与。项目再大首屏只编译首屏用到的模块。我实测过一个中等规模项目冷启动到首屏可交互比传统方案快了一个数量级主要就赢在这里。2.3 单文件组件的三段式拆解细节.vue文件的处理值得单独说因为它是 Vue 项目里出现频率最高的文件类型也是问题高发区。一个典型的 SFC 包含 template、script、style 三部分Vite 插件对它们的处理方式各不相同。template 部分会被vue/compiler-sfc编译成渲染函数。这里有个细节开发阶段编译默认开启了一些调试辅助比如源码位置映射方便你在浏览器里看到报错对应的原始行号。生产构建时会关掉这些产物更小。script 部分如果是script setup会被转换成setup()函数顶层的变量和导入自动暴露给模板。style 部分则根据scoped属性决定是否加作用域标识加了scoped的样式会被改写成带>
企业数字化 ERP 产品动态
相关推荐
AI-Media2Doc:本地化视频转文字工具的功能与部署指南 1. 项目概述:AI-Media2Doc 视频转文字工具最近在 GitHub 发现一个很有意思的开源项目 AI-Media2Doc,它能把你刷的视频自动转换成结构化的文字笔记。作为一个经常需要整理视频内容的自媒体人,我第一时间就下载试用了。这个工具最吸引我的地方是… · 2026/11/5 18:07:40
PostgreSQL 15.0至15.12小版本升级全解析:核心特性、实操路径与避坑指南 1. 为什么值得把 PostgreSQL 15 的小版本吃透PostgreSQL 15 这条线从 15.0 一路走到 15.12,跨度不算短,中间夹着不少“看起来只是修修补补、实际会影响你线上行为”的改动。我见过太多团队的做法是:装个 15.x 就完事,版本号后面那… · 2026/11/5 8:12:26
EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析 1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被… · 2026/11/5 16:49:35
Rust原来很简单二:所有权系统 Part 2 核心篇 —— 所有权系统
本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理
6… · 2026/11/5 16:26:08
基于Hadoop+Spark的民宿智能推荐系统设计与实现 1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配RS485,解决远距离温度监控难题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07
多智能体协作系统架构设计与实践优化 1. 多智能体协作系统的时代背景2017年Transformer架构的诞生彻底改变了人工智能的发展轨迹。当行业还沉浸在单一大模型带来的性能突破时,Anthropic的研究团队已经将目光投向了更前沿的领域——如何让多个智能体通过协作产生超越单体能力的系统智能。这就像交响乐团中… · 2026/11/5 0:00:39
大模型系统性入门实战指南:从原理到部署微调的全链路路线 提到大模型的系统性入门,我先说个结论:这事真不难,难的是资料太散、路线太多,今天这个框架明天那个工具,新人很容易在“收藏夹吃灰”和“教程看到一半放弃”之间反复横跳。市面上关于大模型的内容少说有几十万篇&#… · 2026/11/5 0:00:39
鸿蒙文件系统沙箱机制解析与开发实践 1. 鸿蒙文件系统沙箱机制深度解析作为一名从Android转向鸿蒙开发的工程师,我深刻体会到文件系统访问是迁移过程中最先遇到的"拦路虎"。在Android上运行良好的文件读写代码,在鸿蒙真机环境却频频出现文件写入后神秘消失或直接抛出权限拒绝错误的… · 2026/11/5 0:00:39
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07