tsconfig的target应该设置为多少? 浏览器兼容探索

439 阅读3分钟

转换的东西分成两类: 语法 和 api

语法

我习惯称之为指令, esbuild 语法对照表

targetExample
es2020a?.b
esnextimport "x" with {}

在编译时做转换, 借助AST, 比如 @babel/preset-env

api

也称 polyfill

类(Promise), 原型上的方法Array.prototype.at, 宿主环境的api(<dialog>)

在运行时调用前提供, 常见的有 core-js polyfill.io , 阿里的 polyfill

如何确定大多数用户的浏览器能低能支持哪个esm的语法和api?

  1. 浏览器 ua (不是很准,比如 esbuild 作者手动维护顶层await) browserslist
  2. 特性检测(感觉用的很少) Modernizr , 阮一峰 es-checker

因为语法转换发生在编译时, 所以项目打包前你就得知道用户浏览器版本

除此之外, 有些构建工具可以在构建时帮你注入polyfill, 比如 @babel/preset-env

对于‘ useBuiltIns: ‘ using’’,您不应该自己添加‘ core-js’导入,它们将被自动添加。 请注意,默认情况下 Vite 只处理语法转译,且 不包含任何 polyfill core-js文档链接

因为 vite 完全使用 esbuild (dev 和 build)来转换代码, 而 esbuild 不注入任何polyfill, 见 esbuild.github.io/api/#target

请注意,这仅与语法功能有关,与 API 无关。它不会自动为这些环境未使用的新 API 添加polyfill。您必须明确导入所需 API 的 polyfill(例如通过导入core-js)。自动 polyfill 注入超出了 esbuild 的范围。

此外, esbuild targat值是 esNext, vite 的 build.target 是 特殊值 modules,即 ['es2020', 'edge88', 'firefox78', 'chrome87', 'safari14'], 我感觉vite的默认值完全够用了

在vite中如何添加 polyfill ?

@vitejs/plugin-legacy只会注入polyfill到 <script nomodule>中, 在现在浏览器里,是不会执行这个脚本的, 所以无效

使用 swc 或者 babel-preset,默认情况下,vite在build时是不会使用swc的, swc.rs/docs/config…

在开发时会将 Babel 替换为 SWC。在构建时,若使用了插件则会使用 SWC+esbuild,若没有使用插件则仅会用到 esbuild。

开启swc的方法, 正在探索

react({ plugins: [["@swc/plugin-styled-components", {}]] });

在暂不知道如何开启swc的情况下

  1. (自动)使用babel来转换,接机使用babel/preset-env
  2. (手动)通过ts报错来告知缺失的polyfill,来手动 import 'core-js/actual/'

并不是设置了 target 就会降级所有语法

比如 esbuild 中,就不会处理顶层await,以及太新的提案语法也不会处理, 如果项目中使用ts, 那么ts的相关编译器在转换到js并且处理类型的时候会做一些降级, 剩下的会交给babel等

# "Top-level await is not available in the configured target environment"

[vite:esbuild-transpile] Transform failed with 1 error:
assets/index-!~{001}~.js:511:13: ERROR: Top-level await is not available in the configured target environment ("chrome87", "edge88", "es2020", "firefox78", "safari14" + 2 overrides)

tsconfig 如何配置?

推荐配置

// tsconfig.json
{
compilerOptions:{
   "target": "ES2020", // 因为 vite dev 时的esbuild target是2020 
    "lib": [..., "ES2020",], // 同步添加es2020的类型文件
    "module": "ESNext", // 规定 import 语法如何转换, 比如顶层await,以及cjs还是esm,具体版本不是很重要
    }
 }

github.com/vitejs/vite…

配置es2022不支持.at语法,在vscode里会出现报错,报错来自于 tsconfig中的lib字段

https://polyfill.alicdn.com/polyfill.js?features=Array.prototype.at

image.png

我们会使用core-js做转换,.at是可以使用的, 如何让错误消失呢?

设置 "lib": ["ES2020",...,"ES2022.Array"], 另外依赖于插件usage的按需使用难免有问题, 所以可以采集这个错误,设置到在线 polyfill的query里, 或者直接在文件顶部import core-js/xxx, 也是不错的方法

如果使用eslint, 那么eslint应该也会报错,或者不报错, 都可以使用eslint-plugin-compat 明确告知eslint你的target以及polyfills