尤雨溪-vite多久后能干掉webpack?

2022-10-28 17:47:20 浏览数 (1)

以下内容来自尤雨溪知乎的回答 Vite 的目标不是要干掉 webpack

从定位来说两者就是不一样的:webpack core 是一个纯打包工具(对标 Rollup),而 Vite 其实是一个更上层的工具链方案,对标的是 (webpack 针对 web 的常用配置 webpack-dev-server)。 webpack core 因为只针对打包不预设场景,所以设计得极其灵活,不局限于针对 web 打包,几乎所有可配置的环节都做成了可配置的。这种极度的灵活性对于一些特定场景依然不可替代。但反过来导致的缺点就是配置项极度复杂,插件机制和内部逻辑晦涩难懂,针对常见的 web 也需要大量的配置。另外大量 loader 插件虽然单独发布却存在各种隐式耦合,很容易配置不当互相影响。对于新手来说,把 webpack 从零开始配到跟 Vite 开箱即用功能对等的程度根本是不可能的任务,所以大部分团队/公司要么用的是基于 webpack 包一层的脚手架(umi, vue-cli),或是专门养一个人称 webpack 配置工程师的角色。 Vite 的选择是缩窄预设场景来降低复杂度。如果预设了 web 的场景,那么大部分常见的 web 构建需求都可以直接做成默认内置。由于内置,可以适当的增加各个环节之间的耦合来进一步降低复杂度;同时浏览器场景下意味着可以利用原生 ESM,更进一步又可以基于原生 ESM 实现理论最优性能的热更新。 换言之 Vite 从一开始就不是冲着对标 webpack 100% 使用场景来的。这是一个目标场景 vs. 复杂度的取舍。有些场景,比如针对 Node 打包,本来就不属于 Vite 的目标场景(这个场景可以直接用 esbuild)。但是在纯 web 这个目标场景下,Vite 可以做到在对标 webpack 栈对等功能的前提下极大的降低配置复杂度和提升开发体验。 有些人的态度是这都是不痛不痒的东西 —— 怎么说呢,反正习惯了 Vite 的热更新速度之后你给我钱我也不想再用 webpack。有些人对 Vite 的怀疑其实不是 Vite 本身的问题 —— 核心还是在于已经稳定运行的 webpack 项目要换构建工具是个潜在成本很大的事情,没人愿意背锅而已。比起背锅,还不如多等几秒热更新(唉,也是可以理解的)。

为什么 webpack 抄不了 Vite

看到过不少人的态度是 “webpack 照抄一个不就行了”?如果你真的了解这两个东西,你就会知道抄不了,因为原理完全不一样。webpack 的本质就是先打包,再加载。webpack-dev-server 只是一个在内存里用 webpack 打包的服务器而已。webpack 的一个软肋是 loader / 插件机制跟打包的这个设计前提耦合过深,所以如果 webpack 走 no-bundle 路线跟开一个新项目没多大区别,会跟现有的 loader / 插件生态产生兼容性问题,等于自废武功。相比之下 Rollup 的插件机制就设计得相对更干净简洁,单个模块的 resolve / load / transform 跟打包环节完全解耦,所以 Vite 才能在开发时模拟 Rollup 的插件机制,并且兼容大部分 Rollup 插件。

简单来说,webpack “抄” Vite 的话也就不再是 webpack 了,迁移成本指不定比切 Vite 还高(webpack 5 升级还没整够么?)另一个角度来说,webpack 的打包模式在项目本身源码模块数量极大 (>1000) 的情况下还是有一点优势的,因为浏览器在处理这个级别的并发请求上会产生阻塞(但通常来说如果你一个路由下模块数到这个级别说明你代码分割/按需加载没做好)。

Vite 因为不打包不能上生产

这种属于完全没搞明白 Vite 是啥。简单来说:

  • 开发环境下,模块以原生 esm 的形式被浏览器加载。
  • 生产环境下,模块被 Rollup 以传统方式打包,而且做了很多默认优化。虽然默认是打包的格式也是 ESM,但也可以通过 plugin-legacy 输出其它格式兼容旧浏览器。
  • 开发和生产环境下共享同一套 Rollup 插件机制,所以单个模块的编译在开发和生产环境下是一致的有些人担心一个打包一个不打包会产生不一致,这个理论上存在可能性 —— 本质上这依赖于 Rollup 的打包结果是否符合标准的 ESM semantics,而 Rollup 是一个相当成熟的打包工具了,这一点上还是值得信赖的。另一方面,webpack 开发和生产环境下打包出来的代码也是完全不一样的(你可以调不同的 sourcemap 配置自己看下),所以开发和生产环境不管是用什么工具都存在理论上的不一致问题,实际上只能以用的人够多并且没踩到坑为判断准则。

Vite 跟 Snowpack 的关系

时常能看到有人说是 Snowpack 先搞出 no-bundle 开发的,甚至有人暗示 Vite 是抄了 Snowpack,这里也说说明白。

Snowpack 的前身叫 pika-web,1.x 改名叫 Snowpack。1.x 的 Snowpack 本质上只是一个封装过的 Rollup,核心是把 npm 依赖转换成 esm,目的是能够在原生 ESM 的场景下用 npm 的包。Snowpack 1.x 在服务器这端没有任何逻辑。比如你要用 TS,你得自己起一个 tsc --watch 进程;你要用 babel,你得自己不停地调用 babel-cli。 Vite 的前身是 https://github.com/vuejs/vue-dev-server - 这个概念从一开始就是在服务器端对原生 ESM 请求进行按需编译。Vite 0.x 开始开发的时候是 2020 年 4 月(Commits · vitejs/vite),这个时候的开发目标已经是基于 ESM 实现 HMR 热更新。同时期的 Snowpack 还在 1.7.x(Commits · snowpackjs/snowpack),不仅没有服务端的按需编译,也没有热更新。这个时候 Snowpack 2.0 还在开发中,其作者还在研究 ESM HMR 怎么搞的时候 Vite 已经发布可用的版本了,我们还探讨过通用的 API 标准(https://github.com/snowpackjs/esm-hmr/issues/7)。

所以这里明确一下,无论是 “基于原生 ESM 按需编译“ 还是 ”基于原生 ESM 实现 HMR“,都是 Vite 先提出并实现的。Vite 中确实有一块借鉴了 Snowpack 1.x,就是把依赖预打包从而让 cjs 的依赖也能在原生 ESM 下被使用。

顺道一提,Snowpack 团队现在新做的静态生成框架 Astro,本来基于 Snowpack,现在已经转投 Vite 了(Snowpack 基本弃坑确定)。

Vite 万一弃坑咋办

Vue 以后官方工具全部基于 Vite,这种顾虑就跟当年顾虑 Vue 会不会弃坑一样...

回到主题

我可以肯定的是在 web 场景下 Vite 可以吃下一块稳定的份额。在有些人眼里 Vite 还很新,其实 npm 月下载量已经过百万了。Vue 3 的官方工具链很快就会全面默认推荐 Vite。Nuxt 3 / Storybook 兼容 webpack / Vite;SvelteKit, Astro, Solid 等等新兴框架全部转向 Vite,Shopify 基于 React 的新框架 Hydrogen 也全面押注 Vite。

所以 Vite 能不能干掉 webpack?不限定目标场景的话,肯定不可能,这个也本来就不是 Vite 的目标。如果限定 web 场景,其实也不会,因为 webpack 体量太大,还有 Next 和 Gatsby 这种已经跟它强耦合的大玩家,肯定会对它持续投入,死是肯定死不了的。再说直接一点,纠结这个问题根本没意义,因为开发新工具的目的不是 “干掉竞争对手”,而是让愿意用的人用得爽。我是不太明白为什么有些人总是用一种你死我活的心态去看待开源工具。我开发 Vite 的初衷是让 Vue 用户以后可以少等点 HMR 的时间,后来发现顺道可以让其它框架的用户也受益而已。

0 人点赞