Vite 是怎么兼容老旧浏览器的?你以为仅仅依靠 Babel?
作者:京东科技 孙凯
一、前言
对前端开发者来说,Vite 应该不算陌生了,它是一款基于 nobundle 和 bundleless 思想诞生的前端开发与构建工具,官网对它的概括和期待只有一句话:“下一代的前端工具链”。
Vite 最早的版本由尤雨溪发布于3年前,经历了3年多的发展,Vite 也已逐渐迭代成熟,它的稳定性、扩展性、周边生态足以在生产环境中支撑各种业务场景的落地。但是关于Vite的优劣势分析我们就戛然而止,不在深入展开了,这不是本文的重点。
本文的重点在于探究 Vite 如何实现兼容低版本浏览器,这一切还得从那个阳光明媚的午后说起。
二、那个午后
本着尝鲜的态度,我在某一个项目中用了 Vite,当时还是3.x.x的版本,跟着文档配置,从项目启动到项目构建,一路都很“德芙”(纵享丝滑),在经历了 Vite 带来的短暂新鲜感后,就一直沉浸在业务模块的开发中了,因为在 Vite 刚发布后的那段时间曾看过相关原理解析,是基于浏览器原生的模块化能力按需构建BALABALA等,所以后来 Vite 的这种新鲜感对我而言并没有保持多久。
但直到有天下午我开始打包提测,审查页面元素后发现构建产物居然跟以往 webpack 的产物竟然有点不一样,在好奇心的驱使下,于是我开始尝试解谜。
三、跟webpack构建产物到底哪里不一样?
1. 准备工作
为了能更好的对比两者产物究竟有什么区别,我们首先要确保我们的业务代码基本一致,不一致的地方仅仅是使用不同工具( vite 和 webpack)进行构建,这样才能排除最大干扰因素。
于是我们分别使用最新版的 Vite 和 webpack 初始化了两个页面,为了做作区分,两个页面的仅标题和标题背景不一致,他们在浏览器中渲染后的分别长这个样子:
2. 构建工具版本说明
•Vite:v4.1.4
•webpack:v5.75.0
3. 构建工具配置项说明
•Vite (非常简单,啥也没有)
// vite.config.jsimport { defineConfig } from 'vite'import legacy from '@vitejs/plugin-legacy'import vue from '@vitejs/plugin-vue'export default defineConfig({plugins: [vue(),legacy({targets: ['ios >= 9', 'android >= 4.2', '> 1%']})],server: {host: '127.0.0.1'},build: {minify: false}})•webpack(太多了,也比较常规,就不在这里贴出来全部配置项了,仅在这里配置好跟 Vite 一样的需要兼容到最低的浏览器版本)
// .browserslistrcios >= 9android >= 4.2>1%至此,准备工作完毕,让我们看看两者的构建产物吧。
4. 构建产物
从产物的命名中,我们就能多少看出些许区别,webpack的产物比较简单,中规中矩,而 Vite 的 JS 文件不但比 webpack 多,而且部分文件命名中还多了一个单词:legacy,百度翻译对它的解释是:遗产;遗赠财物;遗留;后遗症;(计算机系统或产品)已停产的,通过翻译,或许你可以猜出来,名字中带 legacy 的文件大概率就是浏览器的兼容文件,那么事实到底是不是这样呢?
如果你足够细心,其实你应该可以从上面 Vite 的配置项代码中嗅到一丝端倪,在 Vite 的配置文件中,有一个名为@vitejs/plugin-legacy的插件,它的名字也包含legacy,Vite 官网中对这个插件的解释是这样的:
“传统浏览器可以通过插件 @vitejs/plugin-legacy 来支持,它将自动生成传统版本的 chunk 及与其相对应 ES 语言特性方面的 polyfill。兼容版的 chunk 只会在不支持原生 ESM 的浏览器中进行按需加载。”
也就是说,这个插件它不但提供了低版本浏览器的兼容能力,还提供了检测是否支持原生 ESM 的能力。那么这个插件都做了哪些事?
主要是以下三点:
1.为最每个生成的 ESM 模块化方式的 chunk 也对应生成一个legacy chunk,同时使用@babel/preset-env转换(没错,Vite 的内部集成了 Babel),生成一个SystemJS模块,关于SystemJS可以看点击这里查看,它在浏览器中实现了模块化,用来加载有依赖关系的各个 chunk。
2.生成 polyfill 包,包含 SystemJS 的运行时,同时包含由要兼容的目标浏览器版本和代码中的高级语法产生的 polyfill。
3.生成
期初我看上面这段代码的时候,我就想:这写的都是些个什么东西!前三行都是高级ES语法,部分浏览器根本不兼容好嘛,这都能写上去,真不怕报错和白屏?
其实要注意 script 标签上type="module"这个属性,ESM模块化的好处之一就是,它在处理报错信息的时候,不像普通 script 一样会把错误抛到模块外部,内部出错也不会阻塞后续逻辑的执行和页面渲染,接下来我们验证一下这个观点,直接上代码:
执行结果如下:
先不管代码结果的输出顺序,我们在这只看输出结果,与上述结论一致的,即错误影响了内部模块,并中断了后续的代码逻辑,而外部不受影响。
在 Vite 生成的 HTML 中这样做的好处就是为了检测浏览器对相关语法的支持程度,如果模块中的语法不支持,就会停止执行;如果支持,那么同时打上一个标记,也就是上述示例代码A的倒数第二行——通过在 window 上设置全局变量(因为ESM模块中的变量影响不到外部)window.__vite_is_modern_browser = true,来标识当前浏览器是否为一个“现代浏览器”,是否支持的某些语法特性(import.meta、动态导入、异步生成器),这样可以使 Vite 后续更准确的判断该加载那些 JS。
于是接下来我们就看到了下面这段代码:
热门文章
常用系统
- 1电脑公司 装机专用系统Windows10 x64 企业装机版 版本1507 2021年10月(64位) ISO镜像高速下载
- 2深度技术Win10激活镜像文件下载_深度技术Win10 32位稳定专业版下载V2021.09
- 3Win10最新版本1909下载_Win10最新版本1909专业版ISO镜像下载
- 4风林火山 GHOST WIN7 SP1 X64 快速安装版 V2023.11 下载
- 5win10专业版纯净版iso下载_win10专业版纯净版iso百度盘下载
- 6新萝卜家园Ghost Win10 极速专业版64位 v2023.03最新免费下载
- 7深度技术 Windows 10 x64 企业版 电脑城装机版2020年12月(64位) 高速下载
- 8电脑公司系统下载_电脑公司ghost win7特别旗舰版下载
- 9Ghost WinXP安装包免费下载_大地系统Ghost WinXP SP3极速装机版下载
- 10雨林木风Ghost Win10 32位精简专业版免费下载V2021.09