vite学习

一、基础概念类

1. 什么是 Vite?它的核心优势是什么?

解答:Vite是尤雨溪开发的新一代前端构建工具,基于浏览器原生ESM和esbuild实现,分为开发服务器和生产构建两部分:

  • 核心优势
  1. 极速开发启动:开发阶段不打包,直接让浏览器加载原生ESM,配合ebuild预购建第三方依赖,启动时间从webpack的秒级变为毫秒级
  2. 热更新(HMR)快:只更新修改的模块,而非全量重建,大型项目热更新耗时<10ms
  3. 按需编译:开发阶段仅编译当前请求的模块,而非全量打包
  4. 内置对Typescript、JSX、CSS、静态资源的支持,无需复杂配置
  5. 生产环境优化:基于Rollup打包,输出高度优化的静态资源,兼顾开发销量和生产性能
2. Vite 为什么比 Webpack 快?

解答 :核心差异在于构建思路底层工具

维度 Vite Webpack
开发阶段打包策略 无打包(原生 ESM 按需加载) 全量打包(构建依赖图谱后输出)
依赖处理 esbuild(Go 编写,快 10-100 倍)预构建第三方依赖 babel/tsc(JS 编写)转译 + 打包
热更新逻辑 只更新修改的模块(精准 HMR) 重新打包修改模块及依赖链
启动耗时 毫秒级(无需等待全量打包) 秒级(需等待全量打包完成)

补充:Vite 并非 "碾压" Webpack,生产环境 Vite 仍用 Rollup 打包(和 Webpack 核心目标一致),优势主要体现在开发阶段

3. Vite 的依赖预构建是什么?为什么需要它?

解答:(核心考点,需结合原理说明)

  • 定义 :Vite 启动时,通过 esbuild 对 node_modules 中的第三方依赖做预处理,输出到 node_modules/.vite 缓存目录。
  • 核心目的
    1. 格式转换:将 CommonJS/UMD 格式的依赖转为 ESM(浏览器原生支持);
    2. 减少请求数:合并细碎依赖(如 lodash-es 数百个文件 → 1 个文件),避免浏览器请求瀑布流;
    3. 缓存优化:预构建结果缓存,后续启动直接复用。
  • 触发时机:首次启动、dependencies 变化、配置变化、手动删除缓存后。
4. Vite 的热更新(HMR)原理是什么?

解答:Vite 的 HMR 基于 WebSocket 实现,核心流程:

  1. 开发服务器监听文件变化;
  2. 文件修改后,Vite 仅编译该模块(而非全量打包);
  3. 通过 WebSocket 通知浏览器 "模块已更新";
  4. 浏览器替换该模块的 ESM 引用,无需刷新页面;
  5. 对.vue/.jsx 等特殊文件,Vite 会触发框架级 HMR(如 Vue 仅更新组件,保留组件状态)。

对比 Webpack:Webpack HMR 需重新构建模块依赖链,Vite 直接操作原生 ESM 模块,更精准、更快。

二、原理深度类

5. Vite 开发服务器的工作流程是什么?

解答:核心流程(从启动到页面加载):

  1. 启动阶段
    • 解析配置文件(vite.config.js);
    • 扫描依赖,通过 esbuild 预构建第三方依赖(输出到 .vite 缓存);
    • 启动 HTTP 服务器 + WebSocket 服务器(用于 HMR)。
  2. 请求处理阶段
    • 浏览器请求 index.html,Vite 注入 HMR 客户端脚本;
    • 解析 html 中的 ESM 模块(如 src/main.js),递归处理 import 语句;
    • 源码模块(.vue/.ts):实时编译为 ESM 并返回;
    • 第三方依赖:返回预构建后的 ESM 文件(从 .vite 缓存读取);
    • 对静态资源:直接返回或处理(如图片转 base64)。
  3. 热更新阶段
    • 监听文件变化 → 编译修改的模块 → WebSocket 通知浏览器 → 替换模块。

6.vite如何处理.vue文件

Vite 对 .vue 单文件组件(SFC)的处理核心依赖官方插件 @vitejs/plugin-vue(Vue 3)/ @vitejs/plugin-vue2(Vue 2),整体流程分为「开发阶段实时编译」和「生产阶段打包优化」两部分,本质是将 .vue 文件拆分为浏览器可识别的原生 ESM 模块(JS/CSS/HTML),以下是详细拆解:

一、核心前置:插件依赖

Vite 本身不内置 .vue 处理逻辑,必须通过官方插件实现,创建 Vue 项目时会自动配置:

bash

运行

复制代码
# Vue 3 项目(自动安装 @vitejs/plugin-vue)
npm create vite@latest my-vue-app -- --template vue
# Vue 2 项目(需手动安装 @vitejs/plugin-vue2)
npm i @vitejs/plugin-vue2 -D

js

复制代码
// vite.config.js 核心配置
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()] // 注册 Vue 插件,开启 .vue 处理能力
})

二、.vue 文件的处理流程(核心)

.vue 文件包含 <template>/<script>/<style> 三部分,Vite 会按「拆分 → 单独处理 → 整合」的逻辑处理,开发和生产阶段的核心流程一致,但优化策略不同。

步骤 1:解析 SFC(拆分三部分)

插件首先将 .vue 文件解析为 AST(抽象语法树),拆分出三个核心块:

  • <script> / <script setup>:逻辑层,处理组件的 JS/TS 逻辑;
  • <template>:模板层,编译为 Vue 渲染函数;
  • <style> / <style scoped> / <style module>:样式层,处理 CSS 预编译、作用域、模块化。
步骤 2:处理 <script> / <script setup>

这是组件的逻辑核心,处理目标是转为原生 ESM 模块:

  1. 语法转译
    • <script setup>:将其编译为普通 <script>(如解析 defineProps/defineEmits/defineExpose 等宏,转为 Vue 运行时可识别的代码);
    • 对 TypeScript:通过 esbuild 快速转译为 JS(开发阶段跳过类型检查,交给 IDE / 构建时的 vue-tsc);
    • 对 JSX/TSX:若使用 <script lang="jsx">,结合 @vitejs/plugin-vue-jsx 转译为渲染函数。
  2. 模块导出
    • 编译后的脚本会导出 Vue 组件选项对象(如 export default { setup(), props: {} });
    • 自动注入 import { createVNode } from 'vue' 等运行时依赖,确保组件能被 Vue 实例化。
步骤 3:处理 <template>

模板最终会被编译为 Vue 渲染函数(render),并注入到脚本模块中:

  1. 模板编译
    • 调用 Vue 3 内置的模板编译器(@vue/compiler-dom),将模板字符串转为渲染函数(如 <div>{``{ msg }}</div>_createVNode("div", null, msg));
    • 处理指令(v-if/v-for/v-bind)、插槽(slot)、事件(@click)等,转为对应的渲染逻辑;
  2. 整合到脚本
    • 若组件没有显式的 setup 函数,编译后的渲染函数会作为 render 选项挂载到组件对象上;
    • 若使用 <script setup>,渲染函数会自动关联到组件的 setup 上下文,保留响应式绑定。
步骤 4:处理 <style>

样式处理分「开发阶段」和「生产阶段」,核心差异是输出形式:

阶段 处理逻辑
开发阶段 1. 编译预处理器(sass/less/stylus)→ 原生 CSS;2. 处理 scoped(添加属性选择器,如 .foo[data-v-xxx]);3. 生成 <style> 标签,通过 JS 动态注入到页面 <head>;4. 支持 HMR:修改样式后仅更新对应的 <style> 标签,不刷新组件。
生产阶段 1. 编译预处理器 + 处理 scoped/module;2. 提取所有组件样式到单独的 CSS 文件(默认 dist/assets/style.xxx.css);3. 支持 CSS 代码分割(按页面 / 组件拆分)、压缩、PostCSS 处理;4. style module 会编译为 CSS 模块对象,注入到组件中。
步骤 5:整合并返回最终模块

将处理后的「脚本(含渲染函数)+ 样式引用」整合为单个 ESM 模块,返回给 Vite 开发服务器 / 生产打包流程:

  • 开发阶段:返回内存中的 ESM 模块,浏览器请求 .vue 文件时直接返回编译结果;
  • 生产阶段:交给 Rollup 打包,合并到最终的 JS/CSS 文件中。

三、特殊场景处理

1. <style scoped> 作用域样式
  • 原理:编译时为组件的根元素添加唯一 data-v-xxx 属性,同时为样式选择器添加该属性后缀(如 .btn.btn[data-v-xxx]),确保样式仅作用于当前组件;

  • 穿透 scoped:支持 :deep()/::v-deep(Vue 2)语法,编译时移除属性后缀,实现子组件样式穿透:

    scss

    复制代码
    <style scoped>
    :deep(.child-class) { color: red; } // 编译后 .child-class[data-v-xxx]
    </style>
2. <style module> CSS 模块
  • 原理:将样式编译为哈希化的类名(如 .title._title_1234_),并导出一个 $style 对象供组件使用:

    vue

    复制代码
    <template>
      <div :class="$style.title">Hello</div>
    </template>
    <style module>
    .title { font-size: 20px; }
    </style>
  • Vite 会将 $style 自动注入到组件的 setup 上下文,无需手动导入。

3. 自定义块(如 <docs>/<i18n>

.vue 文件支持自定义块(如 Vue I18n 的 <i18n>),Vite 需通过插件扩展处理:

js

复制代码
// 处理 <i18n> 块(需安装 @intlify/vite-plugin-vue-i18n)
import vueI18n from '@intlify/vite-plugin-vue-i18n'
export default defineConfig({
  plugins: [
    vue(),
    vueI18n({
      include: path.resolve(__dirname, './src/locales/**')
    })
  ]
})

四、开发 vs 生产阶段的差异

维度 开发阶段 生产阶段
编译时机 浏览器请求 .vue 文件时实时编译 打包时一次性编译所有 .vue 文件
样式输出 动态注入 <style> 标签(HMR 友好) 提取为单独 CSS 文件(支持压缩 / 分割)
性能优化 优先编译速度(跳过压缩 / 深度优化) 优先体积优化(树摇 / 压缩 / 按需加载)
Sourcemap 开启 inline sourcemap(调试友好) 生成单独 .map 文件(可选关闭)

五、常见问题与解决方案

1. .vue 文件编译报错:defineProps is not defined
  • 原因:<script setup> 中的宏未被插件正确编译;
  • 解决方案:确保 @vitejs/plugin-vue 版本与 Vue 版本匹配(Vue 3.2+ 需插件 v4+),并在 vite.config.js 中正确注册插件。
2. <style scoped> 样式不生效
  • 原因:动态创建的 DOM 未携带 data-v-xxx 属性,或选择器优先级问题;
  • 解决方案:使用 :deep() 穿透,或为动态 DOM 手动添加属性。
3. 生产打包后样式丢失
  • 原因:build.cssCodeSplit 关闭导致样式未提取,或自定义块处理不当;

  • 解决方案: js

    复制代码
    // vite.config.js
    build: {
      cssCodeSplit: true // 开启 CSS 代码分割(默认开启)
    }

总结

Vite 处理 .vue 文件的核心逻辑是:

  1. 通过官方插件拆分 SFC 为脚本 / 模板 / 样式三部分;
  2. 脚本转译为 ESM 并处理 <script setup> 宏;
  3. 模板编译为渲染函数并注入脚本;
  4. 样式按环境处理(开发注入标签,生产提取文件);
  5. 整合为原生 ESM 模块,适配 Vite 的按需加载 / 打包逻辑。

整个过程兼顾开发阶段的 "实时编译 + 热更新" 和生产阶段的 "体积优化 + 性能最优",这也是 Vite 处理 Vue 组件比 Webpack+vue-loader 更高效的核心原因(开发阶段无需全量编译,依赖 esbuild 提速)。

相关推荐
Apeng_09191 小时前
vue+canvas实现按下鼠标绘制箭头
前端·javascript·vue.js
源码方舟1 小时前
【华为云DevUI开发实战】
前端·vue.js·华为云
VOLUN1 小时前
封装通用可视化大屏布局组件:Vue3打造高复用性的 ChartFlex/ChartFlexItem
前端·vue.js
细心细心再细心2 小时前
响应式记录
前端·vue.js
北辰alk2 小时前
Vue打包后静态资源图片失效?一网打尽所有解决方案!
vue.js
hjt_未来可期2 小时前
js实现替换输入框中选中的文字
javascript·vue.js
alamhubb2 小时前
前端终于不用再写html,可以js一把梭了,我的ovs(不写html,兼容vue)的语法插件终于上线了
javascript·vue.js·前端框架
m0_740043732 小时前
Vue 组件中获取 Vuex state 数据的三种核心方式
前端·javascript·vue.js
北辰alk2 小时前
Vue动态组件:让组件“活”起来的终极指南
vue.js