shim + sham

shim:是能用的补丁

sham:一些假的方法,只能使用保证不出错,但不能用。为啥会有 sham?因为有些方法的低端浏览器里根本实现不了

例如:es5-shim 和 es6-shim 等古老的补丁方式

babel-polyfill.js

引入包含所有语言层补丁的 babel-polyfill.js。比如:

<script src="<https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.2.5/polyfill.js>"></script>

**缺点:**babel-polyfill 包含所有补丁,不管浏览器是否支持,也不管你的项目是否有用到,都全量引了,

如果用户全都不差流量和带宽(比如内部应用),尽可以用这种方式。

@babel/preset-env + useBuiltins: usage + target

babel-polyfill 包含所有补丁,而只想需要支持某些浏览器的某些版本,是否有办法只包含这些浏览器的补丁?这就是 @babel/preset-env + useBuiltins: usage + target 的配置方案,根据配置的浏览器,产出这些浏览器需要的所有补丁。

示例:

// babel.config.js
module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        corejs: 3, // core-js 版本
        modules: false, // 模块使用 esmodules 语法,不转换
        useBuiltIns: 'usage', // 按需引入 polyfill
      },
    ],
  ],
  plugins: [
    [
      '@babel/plugin-transform-runtime', // 抽离 babel 注入的公共代码
      {
        regenerator: false, // 通过 preset-env 已经使用了全局的 regeneratorRuntime, 不再需要 transform-runtime 提供的 不污染全局的 regeneratorRuntime
        useESModules: true, // 使用 es modules helpers, 不转换 commonJS 语法代码
      },
    ]
  ],
}

问题:

  1. 特性列表是按浏览器整理的,那怎么知道哪些特性我用了,哪些没有用到,没有用到的部分也引入了是不是也是冗余?@babel/preset-env 有提供 exclude 的配置,如果我配置了 exclude,后面是否得小心翼翼地确保不要用到 exclude 掉的特性
  2. 补丁是打包到静态文件的,如果我配置 targets 为 chrome: 62, ie: 9,那意味着 chrome 62 也得载入 ie 9 相关的补丁,这也是一份冗余
  3. 我们是基于 core-js 打的补丁,所以只会包含 ecmascript 规范里的内容,其他比如说 dom 里的补丁,就不在此列,应该如何处理?

手动引入

传统的手动打补丁方案虽然低效,但直观有用。有些非常在乎性能的场景,比如淘宝的部分无线 H5 业务,他们宁可牺牲效率也要追求性能。所以他们的补丁方案是手动引入 core-js/modules 下的文件,缺啥加啥就好。