【原理揭秘】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.js
import { 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 一样的需要兼容到最低的浏览器版本)
// .browserslistrc
ios >= 9
android >= 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 的能力。那么这个插件都做了哪些事?
主要是以下三点:
为最每个生成的 ESM 模块化方式的 chunk 也对应生成一个 legacy chunk,同时使用 @babel/preset-env 转换(没错,Vite 的内部集成了 Babel),生成一个 SystemJS 模块,关于 SystemJS 可以看点击这里查看,它在浏览器中实现了模块化,用来加载有依赖关系的各个 chunk。
生成 polyfill 包,包含 SystemJS 的运行时,同时包含由要兼容的目标浏览器版本和代码中的高级语法产生的 polyfill。
生成
【原理揭秘】Vite 是怎么兼容老旧浏览器的?你以为仅仅依靠 Babel?的更多相关文章
- Css3 兼容新旧浏览器
想想10年前用 IE6,火狐,遨游,谷歌等浏览器学习css时,那叫一个艰苦,各种hack各种抓耳挠腮,不是margin塌陷就是元素飞了... 当前借着css3这个东风,如果各大浏览器厂商能统一一下,也 ...
- 兼容新旧浏览器的flex写法
拷贝直接加类名即可 /* 定义 */ .flex-def { display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older W ...
- (译) Angular运行原理揭秘 Part 1
当你用AngularJS写的应用越多, 你会越发的觉得它相当神奇. 之前我用AngularJS实现了相当多酷炫的效果, 所以我决定去看看它的源码, 我想这样也许我能知道它的原理. 下面是我从源码中找到 ...
- 【转】Angular运行原理揭秘 Part 1
当你用AngularJS写的应用越多, 你会越发的觉得它相当神奇. 之前我用AngularJS实现了相当多酷炫的效果, 所以我决定去看看它的源码, 我想这样也许我能知道它的原理. 下面是我从源码中找到 ...
- HomeKit 与老旧设备
苹果推了HomeKit,已经有很多厂商在做,可以达到Siri控制所有设备的功能. 但是Siri也不是万能的,对人类的语义理解也会产生差错,不过我相信未来这个问题会解决掉. 如果家里有老旧的电视 ...
- Angular 学习笔记 ( 创建 library, 转换老旧的 library )
更新 : 2018-10-28 不知道为什么在 ng 跑一直做不到 .d.ts 最后发现,如果有一个插件 propagating-hammerjs.ts 那么就在 root create 一个 pro ...
- 7款适用老旧设备并对初学者非常友好的轻量级Linux发行版
我们由从 7 到 1 的顺序向大家介绍. 7. Linux Lite 正如其名,Linux Lite 是 Linux 发行版的一个轻量级版本,用户并不需要强大的硬件就可以将它跑起来,而且其使用非常简单 ...
- 【转】HTML5新增元素兼容旧浏览器方法
ref:http://www.jb51.net/html5/163906.html 问题:如何让IE8-兼容这些标签?(需要设计JS中的DOM) 代码如下: <span style=" ...
- mysql8绿色免安装win64版本(自带heidisql.exe客户端)应该兼容老版第三方工具。
https://pan.baidu.com/s/1cvQ4AJX6rmqSpMhBQTPz4Q 如果缺c库,自己去找下. 使用方法:先执行initdb.bat初始化数据 如果要安装为服务:执行inst ...
- 用mongodb 固定集合实现只保留固定数量的记录,自动淘汰老旧数据
在一个保存report记录的场景中,我们使用MongoDB进行数据存储 example: db: report Collection: daily_report 创建db: use report; ...
随机推荐
- Hive+spark工业化项目
DolphinScheduler:国产调度平台 airflow: 调度平台
- UnsupportedOperationException异常
看看下面的例子,这样输出什么呢? public class test { public static void main(String[] args) { String arr = "ab, ...
- ES6知识点总结
声明变量 let 不能重复声明 块级作用域 可修改let变量的值 , const 不能重复声明 块级作用域 不能修改const 变量的值 2. 箭头函数 而箭头函数的this指向函数定义时所 ...
- PTA1003 我要通过! (20 分)
PTA1003 我要通过! (20 分) "答案正确"是自动判题系统给出的最令人欢喜的回复.本题属于 PAT 的"答案正确"大派送 -- 只要读入的字符串满足下 ...
- microbit问题记录
问题: 1.电子罗盘东南西北:不太好用 2. micropython代码:震动.声音显示不对 makecode代码:声音不好用 已解决: 1.摇杆下和左不管用了(已解决:改软件包代码) 2.ma ...
- 对volatile修饰的变量使用memset函数
背景 今天面试了一家公司,面试官问了我一个开放性的问题.大致意思是,为什么对volatile修饰的变量调用memset函数,编译的时候会报错.当然,我是不知道为什么啦.之前没有遇到过嘛.不过我还是做了 ...
- Day02 差点水掉 欸呀呀
Java狂神6.17星期四 知识行 冯诺依曼+图灵 软件+硬件 .......... 快捷键 ctrl+a 全选 ctrl+x 剪切 alt+F4 关闭窗口 win+r 运行 +cmd命令行 win+ ...
- javaweb本地启动很快,服务器上面启动特别慢
在JVM环境中解决 打开$JAVA_PATH/jre/lib/security/java.security这个文件,找到下面的内容: securerandom.source=file:/dev/ura ...
- 3Des加密解密,java c#通用。
1.需要实现对其他系统的单点登陆,我们实现的方法很简单,就是将当前系统的账号通过加密去获取 需要直接登陆上的系统的token,然后访问需直接登陆的系统就带着token,就相当于登陆了. 2.然后呢,我 ...
- Java的由来
Java 发展史 1.1.起源 20 世纪 90 年代,单片式计算机系统诞生,单片式计算机系统不仅廉价,而且功能强大,使用它 可以大幅度提升消费性电子产品的智能化程度. SUN 公司为了抢占市场先机, ...