2021-04-14 --- 由promise.finally()引发的babel知识点

问题记录:

  1. 项目在产线中出现问题,定位问题后发现,是promise.finally() 报错is not a function导致。
  2. 问题只有部分人员出现

定位过程:

  1. 保证代码逻辑没有错误,定位出问题的浏览器,发现都是chrome版本较低的浏览器会报错,大概在60~61版本。
  2. 去MDN查看promise.finally的定义和支持情况,发现是ES7中引入,对chrome浏览器的支持度是83以上。
  3. 到此问题已经定位,但是为什么我们的babel没有polyfill这段代码呢? 因为对babel一直不太熟悉,正好借助这个问题,熟悉一下babel的相关知识点。

一直对babel的概念都停留在它可以自动polyfill新语法的js用来支持老旧浏览器,但是具体的配置情况到底如何,如何识别新语法的js等原理都不甚了解。由于是编译工具,在此只做了解,不做深入学习。

基本用法:

在项目的根目录下创建一个命名为 babel.config.json 的配置文件(需要 v7.8.0 或更高版本),并将以下内容复制到此文件中:

const presets = [
  [
    "@babel/env",
    {
      targets: {
        edge: "17",
        firefox: "60",
        chrome: "67",
        safari: "11.1",
      },
      useBuiltIns: "usage",
      corejs: "3.6.4",
    },
  ],
];

module.exports = { presets };

babel,主要作用是为了兼容浏览器,让你在爽快的使用新特性的同时,不用担心浏览器的兼容问题。 由于项目中使用的是vue-cli生成的脚手架,在使用过程中主要参考vue-cli对babel的配置。

browserslist

@babel/preset-env 和 Autoprefixer 会根据browserlist中的配置来匹配对应的浏览器。

"browserlist":[
  "> 1%",
 "last 2 versions",
 "not ie <= 8"
]

一个默认的 Vue CLI 项目会使用 @vue/babel-preset-app,它通过 @babel/preset-envbrowserslist 配置来决定项目需要的 polyfill。
默认情况下,它会把 useBuiltIns: 'usage' 传递给 @babel/preset-env,这样它会根据源代码中出现的语言特性自动检测需要的 polyfill。这确保了最终包里 polyfill 数量的最小化。然而,这也意味着如果其中一个依赖需要特殊的 polyfill,默认情况下 Babel 无法将其检测出来
如果有依赖需要 polyfill,你有几种选择:

  1. 如果该依赖基于一个目标环境不支持的 ES 版本撰写: 将其添加到 vue.config.js 中的 transpileDependencies 选项。这会为该依赖同时开启语法转换和根据使用情况检测 polyfill。

  2. 如果该依赖交付了 ES5 代码并显式地列出了需要的 polyfill: 你可以使用 @vue/babel-preset-app 的 polyfills 选项预包含所需要的 polyfill。注意 es.promise 将被默认包含,因为现在的库依赖 Promise 是非常普遍的。

  3. 如果该依赖交付 ES5 代码,但使用了 ES6+ 特性且没有显式地列出需要的 polyfill (例如 Vuetify):请使用 useBuiltIns: 'entry' 然后在入口文件添加 import 'core-js/stable'; import 'regenerator-runtime/runtime';。这会根据 browserslist 目标导入所有 polyfill,这样你就不用再担心依赖的 polyfill 问题了,但是因为包含了一些没有用到的 polyfill 所以最终的包大小可能会增加。

babel 实际上使用各种插件来进行polyfill的转换,例如@babel/plugin-transform-arror-functions就是用来转义箭头函数。在整个项目中可能存在很多需要转换的特性,这时候可以直接使用babel的一个preset来进行设置。@babel/preset-env。 在使用vue-cli生成的项目中,默认使用了vue的preset,‘@vue/app’.

preset 中的useBuiltIns

该属性有3个参数:

  1. usage:也就是只包含你所需要的 polyfill,Babel 将检查你的所有代码,以便查找目标环境中缺失的功能,然后只把必须的 polyfill 包含进来。示例代码如下:
Promise.resolve().finally();

会被转换为

require("core-js/modules/es.promise.finally");

Promise.resolve().finally();
  1. entry
    根据配置的浏览器兼容,引入浏览器不兼容的 polyfill。需要在入口文件手动添加 import '@babel/polyfill',会自动根据 browserslist 替换成浏览器不兼容的所有 polyfill。
  2. false
    此时不对 polyfill 做操作。如果引入 @babel/polyfill,则无视配置的浏览器兼容,引入所有的 polyfill。

你可能感兴趣的:(2021-04-14 --- 由promise.finally()引发的babel知识点)