plugin-legacy
2023年12月21日
一、认识
Vite
官方已经为我们封装好了一个开箱即用的方案: @vitejs/plugin-legacy
,我们可以基于它来解决项目语法的浏览器兼容问题。这个插件内部同样使用 @babel/preset-env
以及 core-js
等一系列基础库来进行语法降级和 Polyfill
注入
二、配置
// vite.config.ts
import legacy from '@vitejs/plugin-legacy';
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
// 省略其它插件
legacy({
// 设置目标浏览器,browserslist 配置语法
targets: ['ie >= 11'],
})
]
})
三、效果
在引入插件后,我们可以尝试执行 npm run build
对项目进行打包,可以看到如下的产物信息:
Preview
相比一般的打包过程,多出了 index-legacy.js
、vendor-legacy.js
以及polyfills-legacy.js
三份产物文件。让我们继续观察一下index.html
的产物内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/assets/favicon.17e50649.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
<!-- 1. Modern 模式产物 -->
<script type="module" crossorigin src="/assets/index.c1383506.js"></script>
<link rel="modulepreload" href="/assets/vendor.0f99bfcc.js">
<link rel="stylesheet" href="/assets/index.91183920.css">
</head>
<body>
<div id="root"></div>
<!-- 2. Legacy 模式产物 -->
<script nomodule>兼容 iOS nomodule 特性的 polyfill,省略具体代码</script>
<script nomodule id="vite-legacy-polyfill" src="/assets/polyfills-legacy.36fe2f9e.js"></script>
<script nomodule id="vite-legacy-entry" data-src="/assets/index-legacy.c3d3f501.js">System.import(document.getElementById('vite-legacy-entry').getAttribute('data-src'))</script>
</body>
</html>
通过官方的 legacy
插件, Vite
会分别打包出 Modern
模式和 Legacy
模式的产物,然后将两种产物插入同一个 HTML
里面,Modern
产物被放到 type="module"
的 script
标签中,而 Legacy
产物则被放到带有 nomodule
的 script
标签中。浏览器的加载策略如下图所示:
Preview
这样产物便就能够同时放到现代浏览器和不支持 type="module"
的低版本浏览器当中执行。当然,在具体的代码语法层面,插件还需要考虑语法降级和 Polyfill
按需 注入的问题,接下来我们就来分析一下 Vite
的官方 legacy
插件是如何解决这些问题的。