How to use babel/corejs3/webpack correctly for IE11?

18,871

Solution 1

Using useBuiltIns: "usage"


You'll have to normaly import the modules you want to use (i.g. Postmate) inside your code entry file; no polyfills; every polyfill used will be handled accordingly by @babel/preset-env. Also, the version of corejs in @babel/preset-env has to be a single number (i.e. 3 or 2).

Contents of babel.config.js:

module.exports = function (api) {
  api.cache(true);
  const presets = [
    [
      '@babel/preset-env',
      {
        corejs : {
          version : "3",
          proposals : true
        },
        useBuiltIns: 'usage',
        targets: {
          browsers: [
            "edge >= 16",
            "safari >= 9",
            "firefox >= 57",
            "ie >= 11",
            "ios >= 9",
            "chrome >= 49"
          ]
        }
      }
    ]
  ];
  const plugins= [
      ["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
      ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ];
  return {
    presets,
    plugins
  }
}

Contents of webpackconfig.js:

const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: [
          /\bcore-js\b/,
          /\bwebpack\/buildin\b/
        ],
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            configFile: path.resolve(__dirname, 'babel.config.js'),
            compact: false,
            cacheDirectory: true,
            sourceMaps: false,
          },
        },
      },
    ],
  },
  devtool: "cheap-source-map",
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'shim.js',
  }
}

Contents of entry JS file src/index.js:

import Postmate from 'postmate';

// Postmate and rest of the code
...

It will generate:

dist/shim.js      177K
dist/shim.js.map  140K

You can test an online distributed example working using useBuiltIns: "usage" in IE 11 here: https://zikro.gr/dbg/so/61044894/usage/. (The child iFrame has a button that changes parent window background color to a random color)

You can find a repository with the whole project and the usage example branch in this Github repository/branch: https://github.com/clytras/ie11-postmate/tree/usage

Using useBuiltIns: "entry"


According to this issue disqussion "using Symbol causes exception in IE11", you have to:

  1. Exclude @babel-runtime and core-js in the rule for .js files.
  2. Have corejs: "3" and useBuiltIns: 'entry' to @babel/preset-env preset inside babel.config.js file.
  3. There have to be core-js/stable and postmate imports inside your entry source JS file.

Contents of bavel.config.js:

module.exports = function (api) {
  api.cache(true);
  const presets = [
    [
      '@babel/preset-env',
      {
        corejs:"3",
        useBuiltIns: 'entry',
        targets: {
          browsers: [
            "edge >= 16",
            "safari >= 9",
            "firefox >= 57",
            "ie >= 11",
            "ios >= 9",
            "chrome >= 49"
          ]
        }
      }
    ]
  ];
  const plugins= [
      ["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
      ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ];
  return {
    presets,
    plugins
  }
}

Contents of webpackconfig.js:

const path = require('path');

module.exports = {
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /@babel(?:\/|\\{1,2})runtime|core-js/,
        use: {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            configFile: path.resolve(__dirname, 'babel.config.js'),
            compact: false,
            cacheDirectory: true,
            sourceMaps: false,
          },
        },
      },
    ],
  },
  devtool:"cheap-source-map",
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'shim.js',
  }
}

Contents of entry JS file src/index.js:

import 'core-js/stable';
window.Postmate = require('postmate/build/postmate.min.js');

// Postmate and rest of the code
...

It will generate:

dist/shim.js      641K
dist/shim.js.map  459K

You can test in IE 11 here: https://zikro.gr/dbg/so/61044894/.

Solution 2

You're probably missing some imports, I'd suggest looking at what react-app-polyfills imports under the hood for IE11 support - the error message relates to Symbol. core-js>=3 no longer imports everything that IE11 needs with core-js/stable. At the time of this writing this might suffice:

// If  you need `fetch` or `Object.assign`
npm install whatwg-fetch object-assign
// Make sure we're in a Browser-like environment before importing polyfills
// This prevents `fetch()` from being imported in a Node test environment
if (typeof window !== 'undefined') {
  // fetch() polyfill for making API calls.
  require('whatwg-fetch');
}

// Object.assign() is commonly used with React.
// It will use the native implementation if it's present and isn't buggy.
Object.assign = require('object-assign');

/// This may rid you of your error message

// Support for...of (a commonly used syntax feature that requires Symbols)
require('core-js/features/symbol');
// Support iterable spread (...Set, ...Map)
require('core-js/features/array/from');

Hope this helps

Share:
18,871

Related videos on Youtube

Rhangaun
Author by

Rhangaun

Updated on June 04, 2022

Comments

  • Rhangaun
    Rhangaun about 2 years

    With my current config (see below), I'm getting this error:

       [object Error]{description: "Argument ob...", message: "Argument ob...", name: "TypeError", number: -2147418113, stack: "TypeError: ...", Symbol()_7.bs7gi3oa3wi: undefined}
    

    I tried to dig based on Symbol()_ ... : undefined} but I couldn't find any clear indication.

    This is my .babel.config.js:

    module.exports = function (api) {
        api.cache(true);
        const presets = [
          [
            '@babel/preset-env',
            {
             // modules: false,
              corejs:"3.6.4",
              useBuiltIns: 'usage',
              targets: {
                browsers: [
                  "edge >= 16",
                  "safari >= 9",
                  "firefox >= 57",
                  "ie >= 11",
                  "ios >= 9",
                  "chrome >= 49"
                ]
              }
            }
          ]
        ];
        const plugins= [
            ["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: true }],
            ["@babel/plugin-proposal-class-properties", { "loose": true }]
        ];
        return {
          presets,
          plugins
        }
      }
    

    This is my webpackconfig.js

    module.exports = {
      module: {
        rules: [
          {
            test: /\.js$/,
           // exclude: /node_modules/,
           exclude : [
            /\bcore-js\b/,
            /\bwebpack\/buildin\b/
          ],
            use: {
              loader: 'babel-loader',
              options:{
                sourceType: "unambiguous"
              }
            },
          },
        ],
      },
      devtool:"cheap-source-map",
      resolve: {
        extensions: ['*', '.js'],
      },
      output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'shim.js',
      }
    };
    

    I've also tried many alternatives, this is my current one, with entry:"usage" and not excluding node_modules.

    This is from my package.json:

     "devDependencies": {
        "@babel/core": "^7.9.0",
        "@babel/plugin-proposal-class-properties": "^7.8.3",
        "@babel/plugin-proposal-decorators": "^7.8.3",
        "@babel/preset-env": "^7.9.5",
        "babel-loader": "^8.1.0",
        "eslint": "^6.8.0",
        "eslint-config-google": "^0.14.0",
        "webpack": "^4.42.1",
        "webpack-cli": "^3.3.11",
        "webpack-dev-server": "^3.10.3",
        "dotenv-webpack": "^1.7.0"
      },
      "dependencies": {
        "core-js": "^3.6.4",
        "ismobilejs": "^1.0.3",
        "localforage": "1.7.3",
        "postmate": "^1.5.2",
        "uuid": "^7.0.3"
      }
    

    Error seems to come from the first invocation of the Postmate library i.e. new Postmate({...}) (I have a console.log just before). Prior to this call, I have one to localforage and the promise complete succesfully.

  • Rhangaun
    Rhangaun about 4 years
    I've tried with "core-js" (without /stable) just to see if it makes a difference, but I'm still getting the same error (symbol related).
  • Rhangaun
    Rhangaun about 4 years
    Are you confifent that it can't be achieved with entry:"usage"?
  • Christos Lytras
    Christos Lytras about 4 years
    Why shouldn't be confident? Using usage, imports for polyfills will be added when they are used. You can check it here. Did you try the link that uses Postmate in IE11? It works and properly adds the Symbol polyfills so Postmate won't fail in IE11. What considerations do you have regarding any problems?
  • Rhangaun
    Rhangaun about 4 years
    Your answer is using "entry" not "usage" and it seems to indicate that it can't work with "usage".
  • Christos Lytras
    Christos Lytras about 4 years
    I am pretty aware what my answer uses; I wrote it and I have tested it. I just pointed out what usage is for and its documentation. My question is, what's wrong using entry instead of usage to cover IE11 and even older IE versions support?
  • Christos Lytras
    Christos Lytras about 4 years
    @Rhangaun please check my updated answer. I've included useBuiltIns: 'usage' along with useBuiltIns: 'entry'. Maybe your issue is that you're not importing modules such as postmate.
  • DJ House
    DJ House about 4 years
    Those excludes saved me. Babel kept trying to polyfill core-js which was causing some weird errors for me.
  • Édouard Lopez
    Édouard Lopez almost 3 years
    Thanks, manually install whatwg-fetch object-assign fixed it, then I updated react-app-polyfill to latest and it works. So my package was outdated
  • meistermuh
    meistermuh over 2 years
    thanks so much for your pretty awesome and detailed answer! it helped a lot