通过Webpack babel-loader添加时Promise Polyfill在FireFox和IE11中不起作用

问题描述

我遇到了关于Promfill的以下特殊问题,该问题应该由Babel的预置环境添加,以实现浏览器兼容性。

我有一个Foo.ts文件,该文件使用async/await语法来处理promise。由babel-loader处理,由Webpack开发服务器捆绑并启动后,包含的React Web应用程序在Chrome,Safari,Edge(Mac)中成功运行,但在FireFox,IE11和Edge(Windows)中失败。

错误如下所示,该错误来自@apollo/client所依赖的npm软件包Foo.ts。它是否表明没有应允polyfill?

TypeError: "this.fetchQuery(...).finally is not a function"

babel-loader的Webpack配置如下所示。

module: {
  rules: [
    {
      test: /\.(jsx?|tsx?)$/,exclude: /node_modules\/.*/,use: {
        loader: 'babel-loader',options: {
          presets: [
            '@babel/preset-react','@babel/preset-typescript',[
              '@babel/preset-env',{
                useBuiltIns: 'usage',corejs: '3.6',debug: true,},],plugins: ['react-hot-loader/babel'],]
}

开发服务器启动时,在控制台输出中,我可以看到下面的一行显示诺言polyfill已添加Foo.js

Added following core-js polyfills:
  es.promise { "chrome":"45","edge":"12","firefox":"45","ie":"11","safari":"10.1" }

因此,我很困惑该问题是怎么发生的。

如果我将import 'core-js/es/promise/finally';手动添加Foo.ts,则一切正常。

我想知道这里可能缺少什么,为什么babel-loader无法成功添加polyfill。

Foo.ts中涉及@apollo/client代码部分如下所示。在进行babel转换之前,它已由ES2015编译为tsc目标。

try {
  const response: ApolloQueryResult<QueryType> = await this.apolloClient.query(
    {
      query,fetchPolicy: 'no-cache',errorPolicy: 'all',variables,);
  return response.data;
} catch (e) {
  console.error(e);
  throw e;
}

环境信息

  • Firefox:68.8.0esr
  • @ babel / preset-env:7.9.5
  • core-js:3.6.5
  • Webpack:4.29.6
  • babel-loader:8.0.5

解决方法

进一步研究之后,我认为问题是由@babel/preset-env无法为Firefox注入正确的es.promise polyfill引起的。我使用下面的配置进行了测试,该配置将目标运行环境仅隔离到Firefox。仅对于设置为68及更低版本的Firefox版本才观察到该问题。

      targets: {
        firefox: '68',},

目前,我的解决方法是:

  1. 配置@babel/preset-env以故意排除es.promise填充。
exclude: ['es.promise'],
  1. 通过Webpack的入口点配置添加它,因为仍然需要它。
entry: ['core-js/es/promise','index.ts'],