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
相关推荐
鹏多多38 分钟前
解锁flutter弹窗新姿势:dialog-flutter_smart_dialog插件解读+案例
前端·flutter·客户端
IT_陈寒39 分钟前
Redis 7.0的这个新特性让我处理百万级QPS轻松了50%,你可能还不知道!
前端·人工智能·后端
2301_7965125239 分钟前
Rust编程学习 - 如何快速构建一个单线程 web server
前端·学习·rust
蒜香拿铁1 小时前
Angular【核心特性】
前端·javascript·angular.js
天天向上10241 小时前
vue3 css使用v-bind实现动态样式
前端·css·vue.js
艾小码1 小时前
前端新手必看!困扰90%人的10个JavaScript问题,一次性帮你解决
前端·javascript
xixixin_4 小时前
【React】为什么移除事件要写在useEffect的return里面?
前端·javascript·react.js
嘗_4 小时前
react 源码2
前端·javascript·react.js
我只会写Bug啊8 小时前
Vue文件预览终极方案:PNG/EXCEL/PDF/DOCX/OFD等10+格式一键渲染,开源即用!
前端·vue.js·pdf·excel·预览
扯蛋4389 小时前
LangChain的学习之路( 一 )
前端·langchain·mcp