Ruifeng Ma
Ruifeng Ma

Reputation: 2787

Promise polyfill does not work in FireFox and IE11 when added via Webpack babel-loader

I got hit with below peculiar issue on promise polyfill that should be added by Babel's preset-env for browser compatibility.

I have a Foo.ts file which uses the async/await syntax to handle promises. After being processed by babel-loader, bundled and started by Webpack dev server, the containing React web application runs successfully in Chrome, Safari, Edge(Mac) but fails in FireFox, IE11 and Edge(Windows).

The error looks like below, which is identified to be from the npm package @apollo/client which Foo.ts depends on. Does it indicate that the promise polyfill is missing?

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

The Webpack config for babel-loader looks like below.

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'],
        },
      },
    },
  ]
}

When the dev server starts, in the console output I am able to see below line that says the promise polyfill has been added to Foo.js.

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

Hence I am confused how the problem could have occurred.

If I manually add import 'core-js/es/promise/finally'; to Foo.ts, everything just works.

I am wondering what could be missing here and why that polyfill is not successfully added by babel-loader.

The code portion in Foo.ts that involves @apollo/client looks like below. It's compiled to ES2015 target by tsc before going through babel transformation.

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;
}

Env Info

Upvotes: 2

Views: 2125

Answers (1)

Ruifeng Ma
Ruifeng Ma

Reputation: 2787

After further digging, I think the problem is caused by @babel/preset-env not able to inject the correct es.promise polyfill for Firefox. I tested with below config which isolates the target running environment to Firefox only. The issue is only observed for Firefox version set at 68 and lower.

      targets: {
        firefox: '68',
      },

For now my workaround is:

  1. Config @babel/preset-env to purposely exclude es.promise polyfill.
exclude: ['es.promise'],
  1. Add it through Webpack's entrypoint config since it's still needed.
entry: ['core-js/es/promise', 'index.ts'],

Upvotes: 1

Related Questions