TypeScript 和构建工具(Vite、Webpack等)中构建目标详解

在前端项目中,常常会在 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 方法如 forEachmap
es6es2015 ECMAScript 6 2015 let/const、箭头函数、模块导入导出、Promise、类、解构
es2016 ECMAScript 7 2016 Array.prototype.includes、指数运算符 **
es2017 ECMAScript 8 2017 async/awaitObject.entries/values
es2018 ECMAScript 9 2018 异步迭代器、命名捕获组、Promise.finally
es2019 ECMAScript 10 2019 flatMap、可选 catch 参数、Object.fromEntries
es2020 ECMAScript 11 2020 可选链 ?.、空值合并 ??BigIntPromise.allSettled
es2021 ECMAScript 12 2021 逻辑赋值运算符、字符串 replaceAllWeakRef
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.allSettledBigInt

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.jsontarget 控制 TypeScript 输出的语法;构建工具(Vite/Webpack)的 target 控制最终产物保留哪些语法。
  • 若需要兼容低版本浏览器,还需手动或通过 Babel 插入 polyfill。
  • 建议保持 TypeScript 的 target ≤ 构建工具的 target
  • 在现代浏览器为主的项目中,推荐设置为 es2020
相关推荐
蓝易云12 分钟前
MyBatis注解的运用于条件搜索实践
前端
多啦C梦a16 分钟前
「React事件机制」揭秘:你以为点了按钮,其实点进了事件池!
前端·javascript·react.js
jackyChan17 分钟前
MutationObserver是怎么解决实时性问题
前端
mwq3012320 分钟前
🌈 Vibe Coding - Cursor AI Code Editor 入门指南:AI编程的新范式
前端·人工智能
程序员嘉逸33 分钟前
CSS高级特性全解析
前端
耀耀切克闹灬41 分钟前
web前端基础知识梳理(三)
前端
程序员嘉逸1 小时前
🏗️ CSS布局完全指南:Flex、Grid与Float的终极对决
前端
程序员嘉逸1 小时前
📦 CSS盒模型完全指南:从标准到怪异,再到"三剑客"属性
前端
小高0071 小时前
带新人踩坑实录:行内 onclick 找不到函数?三分钟彻底搞懂作用域!
前端·javascript·面试
程序员嘉逸1 小时前
响应式设计完全指南:打造全设备适配网站
前端