Skip to content

Vite plugin-legacy 详解

· 7 min

先把结论摊开说:plugin-legacy 是给“还吃不动现代 ESM 和新 API”的老浏览器准备的“加餐”。真有用户在用老设备,我们就“花点小钱买安心”;要是你站点 99% 都是新版 Chrome/Safari,劝你忍痛割爱,别为了那 1% 把所有人拖慢。

它到底干啥?#

一句话:打两套包,老少咸宜。

[!tip] 这波属于“多端投喂”:不强迫所有人都吃软饭,但也不饿着老设备。


什么时候该上?三问做决策(别拍脑袋)#

  1. 你的用户里有 iOS 12/13、Android 7/8 的长尾吗?
  2. 有嵌套在古早 WebView(例如某些 X5/厂商定制)的业务必须跑吗?
  3. 上线后“白屏/报错”的反馈来自老设备吗?(埋点+日志说话)

快速上手:三步走就能跑#

安装

Terminal window
npm i -D @vitejs/plugin-legacy
# 或 pnpm add -D @vitejs/plugin-legacy

最小配置

vite.config.ts
import { defineConfig } from 'vite'
import legacy from '@vitejs/plugin-legacy'
export default defineConfig({
plugins: [
legacy({
targets: ['defaults', 'not IE 11', 'iOS >= 12', 'Android >= 7'],
modernPolyfills: true, // 给“准现代”浏览器补上少数新 API
additionalLegacyPolyfills: ['regenerator-runtime/runtime'], // async/await 兜底
renderLegacyChunks: true, // 产出独立的 -legacy 包
externalSystemJS: false, // 内联/本地提供 SystemJS(默认 false)
}),
],
})

怎么验?


配置项#

[!warning] 名字可能不同版本有小差异,但核心思路不变:一套目标(targets)+ 若干补丁(polyfills)+ 两套产物(modern/legacy)。


和 Browserslist / Autoprefixer / Babel 的相处之道#

示例 .browserslistrc

> 0.5%
last 2 versions
not dead
iOS >= 12
Android >= 7

它是怎么工作的?(点到为止,够用了)#


真实场景怎么配?(两档模板)#

legacy({
targets: ['defaults', 'not IE 11', 'iOS >= 12', 'Android >= 7'],
modernPolyfills: true,
additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
})
legacy({
targets: ['>0.3%', 'last 3 versions', 'iOS >= 12', 'Android >= 6'],
modernPolyfills: true,
additionalLegacyPolyfills: [
'regenerator-runtime/runtime',
'core-js/features/array/flat',
'core-js/features/promise/finally',
],
renderLegacyChunks: true,
})

成本账本:别糊里糊涂就开了#

一句话:只要你的老设备用户是真实的、可观的,这点成本值。


踩坑锦集(都是血泪)#


排查套路:怎么确认 legacy 真生效了?#


和团队怎么对齐?(一页纸共识)#


小结#

@vitejs/plugin-legacy 不是“银弹”,但在该用的时候,它就是最省心的那把伞。别迷信“兼容一切”,也别放任“谁爱挂谁挂”。拿数据说话,按需开关,吃该吃的亏,省能省的力——这才是正解。

附一句大白话:别跟浏览器死磕,我们要做的是“让绝大多数用户顺畅抵达”,剩下的,就看业务值不值了。