javascriptecmascript-6babeljsecmascript-5shim

How to Convert Javascript from ES6 to ES5 via Babel, Shim, and Polyfill


I have been trying to make my simple HTML/JS website backwards compatible (IE11 & below) by using Babel and shims/polyfills, but have been unable to do so correctly. My current site uses a few newer functions like Promise(), fetch(), document.querySelectorAll().forEach(), and () => {}.

I have tried adding es6-shim, es5-shim, fetch-polyfill, and promise-polyfill, on top of transpiling my code from es6 -> es5 via Babel. Regardless, when I load my webpage using an older browser (IE 11 or 10 for example), I get multiple errors. The errors say that () => {} does not work, and that .forEach() is not a function, which doesn't make sense since I'm using shims and Babel.

Here is the order of my JS Includes:

[... body content ...]

<script src="assets/libs/es5-shim/es5-shim.min.js" type="text/javascript"></script>
<script src="assets/libs/es6-shim/es6-shim.min.js" type="text/javascript"></script>
<script src="assets/libs/promise-polyfill/promise-polyfill.min.js" type="text/javascript"></script>
<script src="assets/libs/fetch-polyfill/fetch.umd.js" type="text/javascript"></script>

[... rest of scripts ..]

And to transpile my es6 code to es5 I did the following:

npm install -D babel-cli

npm install -D babel-preset-env

// .babelrc

{
  "presets": ["env"]
}
// package.json
...
"scripts": {
  "build": "babel src -d build",
},
...

npm run build

Two example errors: "Object doesn't support property or method forEach" (querySelectorAll().forEach()) and "Syntax error" (() => {})


Solution

  • You're using an old version of Babel, switch to Babel 7 and start using @babel/preset-env. NodeList.forEach won't work in any IE and needs to be polyfilled separately because Babel polyfill doesn't polyfill any missing prototype methods.

    The shortest polyfill is probably

    if (!NodeList.prototype.forEach) NodeList.prototype.forEach = Array.prototype.forEach;
    

    Also you need to configure your .babelrc so your code gets transpiled for IE. Example for Babel 7:

    {
      "presets": [
        [
          "@babel/preset-env",
          {
            "targets": {
              "browsers": ["ie >= 10", "last 1 version"]
            }
          }
        ]
      ]
    }
    

    P.S.: You probably don't need the shims then.