最近前端群里流传一个说法:尤雨溪开始“强推”Vize,要“干掉”Vite。我第一眼看到也愣了一下,心想这是又出了什么新武器,能直接动摇构建工具圈的牌桌?结果冷静下来翻资料才发现,这事多半是把开源社区里的讨论给加工成“标题党”了。
作为从 Webpack 时代一路折腾到 Vite 的开发者,我想借着这个话题把几件事一次说透:Vite 现在到底处于什么位置,“Vize”这名字为什么容易引发误会,以及大家在 Vue 3 + Vite 项目里搜得最多的那些报错,比如 process is not defined、Windows 下 node_options 不是内部或外部命令、打包太慢,到底该怎么处理。这篇不是新闻稿,就是一篇实操经验贴,适合正在用 Vite 写项目、或者准备从老构建工具迁过来的朋友。
1. 先把“干掉 Vite”这句话翻译成人话
1.1 Vize 就算存在,也不是 Vite 的候选接班人
先说结论:“Vize”和“Vite”这两个名字确实容易让人浮想联翩,毕竟只差一个字母,后缀也像。但如果你真去查一圈,会发现市面上叫 Vize 的项目要么是一些可视化状态编辑、页面搭建类工具,要么是某个团队内部的代码生成平台,它们和“构建工具”根本不在一个岗位。
这就好比说“我要用电子秤干掉电饭煲”——都出现在厨房里,但一个管称重,一个管做饭。Vite 解决的是开发服务器启动慢、热更新迟钝、模块打包繁琐的问题;可视化工具解决的是页面状态配置、低代码搭建或者团队协作流程的问题。两者就算出现在同一个项目里,也是上下游协作关系,而不是替代与被替代的关系。
所以当你看到“尤雨溪开始强推 Vize”这种标题时,大概率是有人把某次直播、某条 tweet 或者某个 issue 里的讨论断章取义。前端圈每隔一段时间就会冒这种节奏,套用一句老话:消息越短,谣言越圆。
1.2 尤雨溪“强推”很正常,但别把推广当成审判
至于尤雨溪会不会“强推”某个工具?当然会。不光是 Vite,Vue 生态里的 DevTools、Vitest、VueUse 这些项目他都会在各种场合提。这是开源维护者的本职工作:让更多人知道、试用、反馈,项目才能发展。
但维护者推荐自己的项目,不等于宣布“旧东西已死”。Vue 官方长期维护的 create-vue 这个脚手架,默认就是基于 Vite 的,这意味着 Vite 是 Vue 生态当前的主流配套方案,谈不上被替代。即使以后真出现一个更快的打包底座,那大概率也是 Vite 内部的引擎换了,比如用 Rust 重写的底层模块替换掉 Rollup,而对于普通业务项目来说,使用方式几乎不用变。
换句话说,别听到“新工具”就以为要全部推翻重学。工具链的进化通常是渐进式的:接口变化不大,内部效率提升很多。保持关注的姿势可以,但焦虑完全没必要。
2. Vite 真正站稳脚跟靠的是这三件事
2.1 开发服务器快:esbuild 预构建 + 浏览器原生 ESM
Vite 最出圈的优点就是“启动快”。为什么快?它的核心思路是砍掉了 Webpack 那种“把整个项目打包成 bundle 再启动开发服务器”的模式。
在开发环境下,Vite 会把依赖(node_modules 里的第三方包)用 esbuild 预构建成浏览器能直接识别的 ESM 格式,并且统一成单文件,避免浏览器发起几百个请求去加载一个小包。而项目源码则不打包,直接利用浏览器对原生 ES Module 的支持,按需加载。
打个比方:Webpack 是搬家时把全部家当塞进一个集装箱,再整车运到新家;Vite 是你先在新家把书架、衣柜装好,只开一辆小车,一次次把常用的书和杯子搬过去。刚开始可能还没感觉,一旦项目变大,这种按需加载的收益会非常明显。
热更新同理。源码文件只做按需编译,改一个组件,浏览器只需要重新拉取那个被改动的模块,替换速度几乎是一瞬间的事。这也是 Vite 能让大型项目开发体验有明显提升的根本原因。
2.2 生产构建稳:Rollup 和它的插件生态
开发环境用 esbuild,生产构建却默认用 Rollup,这曾经是很多初学者困惑的点:为什么不直接用 esbuild 打包?
核心原因是:当时 esbuild 在代码分割(code splitting)、Tree Shaking 精细度和产物内容控制上,还达不到大型生产构建的严格要求。Rollup 本身就是为“生成更干净的 ESM 产物”而生的,配合 Vite 的插件机制,能支持各种场景下的产物定制。
这意味着你用 Vite 做生产构建时,得到的仍然是一个经过 Rollup 深度优化的产物。虽然构建速度不如 esbuild 那么极致,但稳定性、兼容性和可定制性都经过了大量线上项目验证。这也是为什么很多企业敢把核心业务迁到 Vite 上,而不是为了图快就去搞一套实验性的构建链路。
2.3 不再只属于 Vue:其他框架也在拿它当底座
还有一个容易被忽略的点:Vite 的通用性。
你可能觉得 Vite 是尤雨溪出的,肯定绑死 Vue。但 Vue 的官方脚手架之外,React、Svelte、Solid 甚至一些纯前端库的模板也都有基于 Vite 的版本。create-vite 这个脚手架本身就提供了 vue、react、svelte、vanilla 等模板选项。
一个构建工具能在多个框架社区里都被接受,说明它解决的是前端通用痛点,而不是某个框架的附属品。依赖它的人越多,生态就越稳,被某个单一版本更新“背刺”的概率反而更低。
3. 网上被问爆的四个 Vite 痛点,建议直接收藏
3.1 process is not defined:为什么浏览器里没有 process
“vite中项目一直报错process is not defined”是高频搜索词。这个报错一般出现在你或者第三方代码里直接访问了process.env.NODE_ENV之类的变量。
原因不复杂:浏览器环境里没有 Node.js 的process对象。Webpack 打包时会自动做一部分 polyfill 和变量替换,让你在浏览器代码里使用 process.env 也不报错;Vite 默认不做这种“兜底”,它更希望你显式声明,或者直接改用标准的import.meta.env。
遇到这个报错,第一步应该定位是哪段代码在访问 process。如果是自己的业务代码,直接改成:
// 原来 const isDev = process.env.NODE_ENV === 'development' // 改成 const isDev = import.meta.env.DEV如果是某个第三方包在访问 process.env,可以先看这个包是否提供了浏览器专用版本。有些包在 package.json 里写了 browser 字段,Vite 会自动按浏览器版本解析。实在绕不开,再在 vite.config.js 里做一次显式的变量替换:
import { defineConfig } from 'vite' export default defineConfig({ define: { 'process.env.NODE_ENV': JSON.stringify('production') } })这里要提醒一句:define本质是“把标识符替换成另一个字符串”,不是给浏览器塞一个完整的 Node 环境。所以不要幻想它能解决所有 process 相关调用,比如process.cwd()、process.nextTick()这类 API 就没有办法通过 define 简单替换。能不用就不用,第三方包的问题优先找替代包。
3.2 node_options 在 Windows 上“不是内部或外部命令”
这个报错经常出现在网上复制命令时,尤其像:
$ node_options=--max-old-space-size=4096 vite在 Linux 或 macOS 的 bash 里,这种写法可以用;但放到 Windows 的 cmd 或 PowerShell 里,shell 会把node_options当成一个程序名去执行,然后报“不是内部或外部命令”。原因就是跨平台的 shell 语法差异,不是 Vite 本身的问题。
在 Windows 上有三种稳妥的解决办法:
第一种,用 PowerShell 设置临时环境变量:
$env:NODE_OPTIONS="--max-old-space-size=4096" vite第二种,用 cmd 的命令行语法:
set NODE_OPTIONS=--max-old-space-size=4096 vite第三种,也是我最推荐的方式:不要手动敲这串东西,而是写进 package.json,配合 cross-env 保证跨平台可用:
{ "scripts": { "dev": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite", "build": "cross-env NODE_OPTIONS=--max-old-space-size=4096 vite build" } }npm install -D cross-env这样在 Windows、macOS、Linux 以及 CI 环境里跑的命令都一样,不会出现“我本地明明能跑,CI 上就挂”的尴尬情况。
3.3 打包太慢,先别急,用数据说话
“vite打包太慢”也是高频搜索,但这个说法得分情况看。Vite 开发环境快,不代表生产构建就一定快,因为生产构建默认走 Rollup。遇到构建慢,先不要凭感觉吐槽,按下面几步排查:
第一,确认是不是 sourcemap 拖慢的。有些人习惯开启build.sourcemap用于线上排查,但 sourcemap 会显著拉长构建时间并增大产物体积。如果只是临时排查问题,建议在 CI 构建里关掉:
export default defineConfig({ build: { sourcemap: false } })第二,用可视化插件看产物情况和耗时分布:
npm install -D rollup-plugin-visualizerimport { visualizer } from 'rollup-plugin-visualizer' export default defineConfig({ plugins: [ visualizer({ open: true, gzipSize: true, filename: 'dist/stats.html' }) ] })跑一次构建后打开 stats.html,能明显看到哪些依赖占的体积最大。通常你会发现是某个重型可视化库、日期处理库或者 UI 组件库全家桶。针对体积最大的依赖,再做按需引入或 CDN 外置。
第三,检查有没有把不需要解析的文件也交给 Vite 处理。比如 node_modules 里的某个包不需要再做 TS 转译,就可以在 optimizeDeps.exclude 里排除掉,减少预构建时间。
第四,合理配置build.rollupOptions.output.manualChunks,把不常变动的第三方依赖单独拆出来,让浏览器缓存生效。这里的收益不是直接缩短第一次构建时间,而是让后续构建和用户二次访问更快:
import { defineConfig } from 'vite' export default defineConfig({ build: { rollupOptions: { output: { manualChunks(id) { if (id.includes('node_modules')) { if (id.includes('vue')) return 'vue-vendor' if (id.includes('echarts')) return 'echarts-vendor' return 'vendor' } } } } } })最后,别忘了 Vite 的构建缓存。虽然生产构建没有开发环境那么强的缓存机制,但保持依赖版本稳定、避免每次构建前都强制清 node_modules,都能减少不必要的重复开销。
如果以上都做了还是慢,你就要接受一个现实:超大项目的生产构建本来就不可能像开发模式一样毫秒级,这时候可以做的是项目结构优化,而不是继续压榨构建工具。
3.4 用 Vite 从零创建 Vue3 项目要选哪些预设
如果你还没用过 Vite,最直接的体验方式是从脚手架开始:
npm create vue@latest这是 Vue 官方基于 Vite 的脚手架,比 vite 原生的 vue 模板多了更完整的工程化选项。执行后会问你要不要启用 TypeScript、Vue Router、Pinia、Vitest、ESLint、Prettier 等。
我的经验是:新项目直接上 TypeScript + Vue Router + Pinia + ESLint,这几样是大部分业务项目的标配。Vitest 和端到端测试件可以看团队情况选,不用一上来全勾,避免脚手架生成一堆你没时间维护的配置。
如果你只想最小化尝试 Vite,也可以:
npm create vite@latest my-app -- --template vue-ts创建完成后进目录,安装依赖,跑npm run dev,前后也就一两分钟。你会在终端看到 Vite 那行提示,浏览器打开后就是 Vue3 + Vite 的启动页。
4. 迁移到 Vite 后真正会改变的细节
4.1 环境变量:从 process.env 到 import.meta.env
迁移项目时最容易改出问题的就是环境变量。Webpack 时代常用process.env.XXX,Vite 里统一改成import.meta.env.XXX,而且只有以VITE_开头的变量才会被暴露到客户端代码里。
在你的项目根目录建.env.development和.env.production:
# .env.development VITE_API_BASE_URL=/api VITE_APP_TITLE=本地环境# .env.production VITE_API_BASE_URL=https://api.example.com VITE_APP_TITLE=线上环境然后在代码里访问:
const apiBase = import.meta.env.VITE_API_BASE_URL需要注意,Vite 不会自动替换process.env.NODE_ENV以外的 process 变量,所以迁移时要全局搜一遍业务代码里的process.env.,全部换掉。如果你的代码里还用了process.browser之类的自定义字段,那基本是某个库的坑,优先考虑升级或者换库。
4.2 微前端接入 vue3 + vite 的实战要点
“vue3 + vite + 微前端方案”也是热搜词。微前端的本质是把多个独立应用组合成一个整体,Vite 只是其中一个应用的构建工具。所以重点不是 Vite 怎么“支持”微前端,而是你的主应用、子应用之间怎么约定通信和生命周期。
目前有两类常见方案:一类是 Webpack 时代的 qiankun,一类是基于 Module Federation 思想的方案,比如 @originjs/vite-plugin-federation。
以 qiankun 为例,Vite 子应用接入时常见的问题是:子应用是原生 ESM 产物,而 qiankun 的 JS 沙箱机制对 ESM 的支持比较有限。很多团队的做法是让 Vite 子应用单独部署成一个页面,主应用通过 iframe 或者指定路径加载,而不是完全依赖 qiankun 的 JS 加载机制。
用 Vite 构建子应用时,有几个配置需要额外注意:
- 子应用要设置明确的 base 路径,不然部署到子路径时资源会 404。
- 开发环境下子应用要开 CORS,主应用才能跨域拉取资源。
- 生命周期函数要挂到 window 上,方便主应用识别。
使用 vite-plugin-federation 的话,配置会更贴近 Module Federation 的写法:
import federation from '@originjs/vite-plugin-federation' export default defineConfig({ plugins: [ federation({ name: 'remote_app', filename: 'remoteEntry.js', exposes: { './App': './src/App.vue' }, shared: ['vue'] }) ], build: { target: 'esnext' } })不过要冷静看待这套方案:Micro-frontend 的难点从来不是构建工具,而是团队如何确定应用边界、如何处理公共依赖、如何做样式隔离。如果在这些方面没有落地,换成 Vite 也救不了微前端项目。
4.3 我整理的一份常见报错对照表
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
| process is not defined | 浏览器里没有 Node 的 process 对象 | 业务代码改用 import.meta.env;第三方包用 define 做变量替换或换包 |
'node_options' 不是内部或外部命令 | Windows cmd 无法识别 Linux shell 语法 | 用 PowerShell 的 $env:NODE_OPTIONS 或 cross-env |
| 打包很慢 | sourcemap 开启、依赖过大、未做拆包 | 关闭 sourcemap,用 visualizer 定位体积瓶颈,配置 manualChunks |
| 刷新后 404 | 项目部署在子路径但未设置 base | vite.config 里配置base: '/子路径/' |
| 静态资源加载 404 | public 目录或相对路径使用错误 | 资源放 public 下用/xxx.png,或使用 import.meta.env.BASE_URL |
| 启动后样式丢失 | 某些 CSS 库和 Vite 的 CSS 处理顺序不一致 | 检查样式导入顺序,将全局样式放在入口最先导入 |
这表格里的常见问题,几乎都是配置层面能解决的。碰到陌生报错,优先看 Vite 的官方文档和对应版本 changelog,比在网络上直接搜索未知绕路更高效。
5. 下一代构建工具正在路上,但不用慌
5.1 Vite 接下来的升级重点:向原生速度靠拢
Vite 的开发体验已经不错,但它不是停滞不前。前端的趋势是把更多重活交给原生语言处理,比如用 Rust 写底层打包逻辑,替代掉纯 JavaScript 的模块分析和转译部分。这就是为什么开源社区里能看到各种 rust 工具链的实验项目,例如 rolldown-vite 这类方向的研究。
如果底层引擎重写完成,Vite 会保留现有配置和插件体系,但生产构建速度会接近开发模式的体验。这对普通开发者来说,意味着你在写配置时不用学一套新东西,收益却非常直接。这也是工具链进化的理想状态:接口稳定、内部重写。
所以回归到“干掉 Vite”这个话题。与其担心被谁干掉,不如关心它接下来会把哪些内部模块升级掉。工具换代不是朝令夕改,而是旧接口被新实现一点点替换。
5.2 什么情况不建议立刻迁移
虽然我推荐 Vite,但也要实话实说:不是所有项目都适合立刻迁。
如果你的老项目里有大量自定义 Webpack loader 或插件,比如公司内部开发的特殊资源处理逻辑、自定义的构建流程钩子、和私服联动做的依赖注入,那迁移成本会很高。这种情况硬迁 Vite,你可能要花好几周去重写工程化代码,而业务本身一点没动,这就是工具改造影响业务推进的典型反面教材。
另外,如果你的线上应用还在兼容非常老的浏览器,比如 IE 11,Vite 的默认兼容策略会比较麻烦,需要额外配置@vitejs/plugin-legacy,产物也会随之复杂化。如果项目已经没有精力维护这种兼容层,那也先别动。
5.3 什么时候迁移性价比最高
最适合引入 Vite 的时机有这么几种:
- 新项目启动。没有任何历史包袱,直接用 Vite 搭建,成本最低。
- 老项目开发体验极差。启动要等一分钟、保存一次要卡几秒,这种项目迁移到 Vite 后,团队幸福感提升非常明显。
- 你想拆分微前端或独立部署模块时。Vite 对 ESM 和 Modern Web 标准的友好程度,让每个子应用可以独立开发、独立构建、独立部署。
迁移时建议先小步验证:在一个不核心的业务模块上试点,跑通开发、构建、部署、线上监控全流程后,再决定是否扩展到更多应用。不要一上来就全量切换,工程化改造最怕“大爆炸式发布”。
6. 最后说点个人体会
做前端这些年,我经历过的“要被干掉”传闻少说也有七八回。当年有人喊 Webpack 要完,也有人说 esbuild 会取代一切,结果到现在,Vite 和 Webpack 还在各自适用的场景里共存。工具选择本质上是一个“成本-收益”问题,不是“信仰-站队”问题。
如果你正在犹豫要不要换 Vite,我的建议是别只看新闻,先自己动手。找个下午,在一个临时目录里跑一遍npm create vue@latest,把常用功能都试一遍,感受一下热更新和打包流程,比看十篇文章都管用。如果在迁移过程中遇到解决不了的问题,再针对性地查文档、看 issue,通常都能找到答案。
补一个我自己的小习惯:每次接到一个新项目或者准备升级构建工具前,我都会特意记下当前项目从克隆到跑起来的时间、保存一次代码到页面刷新的时间、生产构建的耗时。等切换完 Vite 之后再对比一次。数据清楚了,别人再怎么说“Vite 不行”或“Vite 无所不能”,你都有自己的一杆秤。