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

在前端项目中,常常会在 TypeScript、Vite、Webpack、Babel 等工具中看到类似如下配置项:

"target": "es2020"

这些配置中的 "es5""es6""es2020""esnext" 是 ECMAScript 的不同版本标识,决定了构建产物所使用的语法标准。本篇文章将系统梳理这些标准的区别,并深入讲解:

  • 各版本的差异
  • tsconfig.json 中的 target 与构建工具中 target 的关系
  • 如何配置 polyfill 以支持旧浏览器

各版本 ECMAScript 的语法差异

构建目标等价标准发布年份主要新特性
es5ECMAScript 52009严格模式、getter/setter、Array 方法如 forEach、map
es6 或 es2015ECMAScript 62015let/const、箭头函数、模块导入导出、Promise、类、解构
es2016ECMAScript 72016Array.prototype.includes、指数运算符 **
es2017ECMAScript 82017async/await、Object.entries/values
es2018ECMAScript 92018异步迭代器、命名捕获组、Promise.finally
es2019ECMAScript 102019flatMap、可选 catch 参数、Object.fromEntries
es2020ECMAScript 112020可选链 ?.、空值合并 ??、BigInt、Promise.allSettled
es2021ECMAScript 122021逻辑赋值运算符、字符串 replaceAll、WeakRef
es2022ECMAScript 132022类字段、顶级 await、.at() 方法
esnext最新提案--表示“构建时支持的最新语法”,可能包含实验特性

TypeScript tsconfig.json 中的 target

{
  "compilerOptions": {
    "target": "es2020"
  }
}

target 控制 TypeScript 输出的 JavaScript 使用的 语法级别

  • ✅ 是否保留 async/await
  • ✅ 是否保留箭头函数
  • ✅ 是否使用模块语法 import/export
  • ❌ 不影响内置 API,如 Promise.allSettled 是否存在(需另加 polyfill)

构建工具中的 target(Vite、esbuild、Webpack)

Vite / esbuild 示例

export default defineConfig({
  build: {
    target: 'es2020'
  }
})
  • 控制构建产物保留的语法,如 ?.??import.meta
  • 不会自动插入 polyfill(如 Promise.allSettledBigInt

Webpack + Babel 示例

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
兼容 IE11es5es5
支持现代浏览器es2020es2020
Electron/Node.js 环境es2022es2022
尽可能现代(实验)esnextesnext

Vite 和 esbuild 中如何引入 polyfill?

构建工具默认不插入 polyfill

Vite 使用 esbuild,只负责语法转换,不会自动处理以下情况:

Promise.allSettled([...]);
Object.fromEntries(...);
BigInt(123);

方法一:手动引入 core-js polyfill(推荐)

// 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(兼容性优先)

// babel.config.json
{
  "presets": [
    [
      "@babel/preset-env",
      {
        "useBuiltIns": "usage",
        "corejs": 3
      }
    ]
  ]
}

并在 vite.config.ts 中接入 Babel 插件:

import legacy from '@vitejs/plugin-legacy';

export default defineConfig({
  plugins: [
    legacy({
      targets: ['defaults', 'not IE 11']
    })
  ]
});

方法三:使用 http://polyfill.io CDN(公网项目)

<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自动处理、完整兼容构建慢、体积大兼容性要求高的公共项目
http://polyfill.io CDN动态按需加载依赖网络、不适合私有部署对公网用户兼容老设备

总结

  • target 配置决定构建产物所使用的 JS 语法版本。
  • tsconfig.json 的 target 控制 TypeScript 输出的语法;构建工具(Vite/Webpack)的 target 控制最终产物保留哪些语法。
  • 若需要兼容低版本浏览器,还需手动或通过 Babel 插入 polyfill。
  • 建议保持 TypeScript 的 target ≤ 构建工具的 target
  • 在现代浏览器为主的项目中,推荐设置为 es2020
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值