在前端项目中,常常会在 TypeScript、Vite、Webpack、Babel 等工具中看到类似如下配置项:
            
            
              json
              
              
            
          
          "target": "es2020"
        这些配置中的 "es5"、"es6"、"es2020"、"esnext" 是 ECMAScript 的不同版本标识,决定了构建产物所使用的语法标准。本篇文章将系统梳理这些标准的区别,并深入讲解:
- 各版本的差异
 tsconfig.json中的target与构建工具中target的关系- 如何配置 polyfill 以支持旧浏览器
 
各版本 ECMAScript 的语法差异
| 构建目标 | 等价标准 | 发布年份 | 主要新特性 | 
|---|---|---|---|
es5 | 
ECMAScript 5 | 2009 | 严格模式、getter/setter、Array 方法如 forEach、map | 
es6 或 es2015 | 
ECMAScript 6 | 2015 | let/const、箭头函数、模块导入导出、Promise、类、解构 | 
es2016 | 
ECMAScript 7 | 2016 | Array.prototype.includes、指数运算符 ** | 
es2017 | 
ECMAScript 8 | 2017 | async/await、Object.entries/values | 
es2018 | 
ECMAScript 9 | 2018 | 异步迭代器、命名捕获组、Promise.finally | 
es2019 | 
ECMAScript 10 | 2019 | flatMap、可选 catch 参数、Object.fromEntries | 
es2020 | 
ECMAScript 11 | 2020 | 可选链 ?.、空值合并 ??、BigInt、Promise.allSettled | 
es2021 | 
ECMAScript 12 | 2021 | 逻辑赋值运算符、字符串 replaceAll、WeakRef | 
es2022 | 
ECMAScript 13 | 2022 | 类字段、顶级 await、.at() 方法 | 
esnext | 
最新提案 | -- | 表示"构建时支持的最新语法",可能包含实验特性 | 
TypeScript tsconfig.json 中的 target
        
            
            
              json
              
              
            
          
          {
  "compilerOptions": {
    "target": "es2020"
  }
}
        target 控制 TypeScript 输出的 JavaScript 使用的 语法级别:
- ✅ 是否保留 
async/await - ✅ 是否保留箭头函数
 - ✅ 是否使用模块语法 
import/export - ❌ 不影响内置 API,如 
Promise.allSettled是否存在(需另加 polyfill) 
构建工具中的 target(Vite、esbuild、Webpack)
Vite / esbuild 示例
            
            
              ts
              
              
            
          
          export default defineConfig({
  build: {
    target: 'es2020'
  }
})
        - 控制构建产物保留的语法,如 
?.、??、import.meta - 不会自动插入 polyfill(如 
Promise.allSettled、BigInt) 
Webpack + Babel 示例
            
            
              js
              
              
            
          
          presets: [
  ['@babel/preset-env', {
    targets: '> 0.25%, not dead',
    useBuiltIns: 'usage',
    corejs: 3
  }]
]
        - Babel 会根据目标环境:
- 降级语法
 - 自动插入 polyfill(结合 
core-js) 
 
TypeScript target 与构建工具 target 的关系
| 项目 | TypeScript target | 
构建工具 target | 
|---|---|---|
| 控制语法降级 | ✅ 是 | ✅ 是 | 
| 控制 API 支持 | ❌ 否 | ❌ 否(需 polyfill) | 
| 控制代码压缩语法 | ❌ 否 | ✅ 是(如 Terser) | 
| 控制 tree-shaking | ❌ 否 | ✅ 是(现代语法更利于优化) | 
推荐配置建议
TypeScript 的
target不要高于构建工具的target。
否则可能出现:
- 构建工具无法解析新语法,导致构建失败或运行时报错。
 esbuild不会再对降级后的语法进行优化,导致文件体积变大。
| 场景 | tsconfig.json 中 target | 构建工具中 target | 
|---|---|---|
| 兼容 IE11 | es5 | 
es5 | 
| 支持现代浏览器 | es2020 | 
es2020 | 
| Electron/Node.js 环境 | es2022 | 
es2022 | 
| 尽可能现代(实验) | esnext | 
esnext | 
Vite 和 esbuild 中如何引入 polyfill?
构建工具默认不插入 polyfill
Vite 使用 esbuild,只负责语法转换,不会自动处理以下情况:
            
            
              js
              
              
            
          
          Promise.allSettled([...]);
Object.fromEntries(...);
BigInt(123);
        方法一:手动引入 core-js polyfill(推荐)
        
            
            
              ts
              
              
            
          
          // main.ts
import 'core-js/features/promise/all-settled';
import 'core-js/features/object/from-entries';
import 'core-js/features/array/flat-map';
        适用于只 polyfill 项目实际用到的部分,构建体积更小、控制更精细。
方法二:通过 Babel 插入 polyfill(兼容性优先)
            
            
              json
              
              
            
          
          // babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}
        并在 vite.config.ts 中接入 Babel 插件:
            
            
              ts
              
              
            
          
          import legacy from '@vitejs/plugin-legacy';
export default defineConfig({
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11']
    })
  ]
});
        方法三:使用 polyfill.io CDN(公网项目)
            
            
              html
              
              
            
          
          <script src="https://polyfill.io/v3/polyfill.min.js?features=default,Promise.allSettled"></script>
        特点:
- 根据浏览器 User-Agent 自动加载缺失的 polyfill
 - 不适用于内网、Electron、App 内嵌 WebView 等场景
 
polyfill 方案对比总结
| 方法 | 优点 | 缺点 | 适用场景 | 
|---|---|---|---|
手动引入 core-js | 
控制精细、体积小 | 需手动维护 | 大多数项目 | 
| Babel 插入 polyfill | 自动处理、完整兼容 | 构建慢、体积大 | 兼容性要求高的公共项目 | 
| polyfill.io CDN | 动态按需加载 | 依赖网络、不适合私有部署 | 对公网用户兼容老设备 | 
总结
target配置决定构建产物所使用的 JS 语法版本。tsconfig.json的target控制 TypeScript 输出的语法;构建工具(Vite/Webpack)的target控制最终产物保留哪些语法。- 若需要兼容低版本浏览器,还需手动或通过 Babel 插入 polyfill。
 - 建议保持 TypeScript 的 
target≤ 构建工具的target。 - 在现代浏览器为主的项目中,推荐设置为 
es2020。