Next.js: Babel polyfill doesn't seem to be injected

Created on 5 Jul 2017  ·  34Comments  ·  Source: vercel/next.js

I'm trying to support IE11 for my app to fix the error
TypeError: Object doesn't support property or method 'find'

Using next 2.4.6 but also not working on latest beta

Added a custom .babelerc together with babel-preset-env with the following config:

{
  "presets": [
    "es2015",
    "react",
    "next/babel",
    "stage-0",
    [ "env", {
      "targets": {
        "safari": 10,
        "ie": 11
      },
      "modules": false,
      "useBuiltIns": true,
      "debug": true
    }]
  ],
}

Enabled the debug flag so on startup I get the following log, which seems to mean that the polyfill are added.

babel-preset-env: `DEBUG` option

Using targets:
{
  "safari": "10",
  "ie": "11"
}

Modules transform: false

Using plugins:
  check-es2015-constants {"ie":"11"}
  transform-es2015-arrow-functions {"ie":"11"}
  transform-es2015-block-scoping {"ie":"11"}
  transform-es2015-classes {"ie":"11"}
  transform-es2015-computed-properties {"ie":"11"}
  transform-es2015-destructuring {"ie":"11"}
  transform-es2015-duplicate-keys {"ie":"11"}
  transform-es2015-for-of {"ie":"11"}
  transform-es2015-function-name {"ie":"11"}
  transform-es2015-literals {"ie":"11"}
  transform-es2015-object-super {"ie":"11"}
  transform-es2015-parameters {"ie":"11"}
  transform-es2015-shorthand-properties {"ie":"11"}
  transform-es2015-spread {"ie":"11"}
  transform-es2015-sticky-regex {"ie":"11"}
  transform-es2015-template-literals {"ie":"11"}
  transform-es2015-typeof-symbol {"ie":"11"}
  transform-es2015-unicode-regex {"ie":"11"}
  transform-regenerator {"ie":"11"}
  transform-exponentiation-operator {"safari":"10","ie":"11"}
  transform-async-to-generator {"safari":"10","ie":"11"}
  syntax-trailing-function-commas {"ie":"11"}

Using polyfills:
  es6.typed.array-buffer {"ie":"11"}
  es6.typed.int8-array {"ie":"11"}
  es6.typed.uint8-array {"ie":"11"}
  es6.typed.uint8-clamped-array {"ie":"11"}
  es6.typed.int16-array {"ie":"11"}
  es6.typed.uint16-array {"ie":"11"}
  es6.typed.int32-array {"ie":"11"}
  es6.typed.uint32-array {"ie":"11"}
  es6.typed.float32-array {"ie":"11"}
  es6.typed.float64-array {"ie":"11"}
  es6.map {"ie":"11"}
  es6.set {"ie":"11"}
  es6.weak-map {"ie":"11"}
  es6.weak-set {"ie":"11"}
  es6.reflect.apply {"ie":"11"}
  es6.reflect.construct {"ie":"11"}
  es6.reflect.define-property {"ie":"11"}
  es6.reflect.delete-property {"ie":"11"}
  es6.reflect.get {"ie":"11"}
  es6.reflect.get-own-property-descriptor {"ie":"11"}
  es6.reflect.get-prototype-of {"ie":"11"}
  es6.reflect.has {"ie":"11"}
  es6.reflect.is-extensible {"ie":"11"}
  es6.reflect.own-keys {"ie":"11"}
  es6.reflect.prevent-extensions {"ie":"11"}
  es6.reflect.set {"ie":"11"}
  es6.reflect.set-prototype-of {"ie":"11"}
  es6.promise {"ie":"11"}
  es6.symbol {"ie":"11"}
  es6.object.assign {"ie":"11"}
  es6.object.is {"ie":"11"}
  es6.function.name {"ie":"11"}
  es6.string.raw {"ie":"11"}
  es6.string.from-code-point {"ie":"11"}
  es6.string.code-point-at {"ie":"11"}
  es6.string.repeat {"ie":"11"}
  es6.string.starts-with {"ie":"11"}
  es6.string.ends-with {"ie":"11"}
  es6.string.includes {"ie":"11"}
  es6.regexp.flags {"ie":"11"}
  es6.regexp.match {"ie":"11"}
  es6.regexp.replace {"ie":"11"}
  es6.regexp.split {"ie":"11"}
  es6.regexp.search {"ie":"11"}
  es6.array.from {"ie":"11"}
  es6.array.of {"ie":"11"}
  es6.array.copy-within {"ie":"11"}
  es6.array.find {"ie":"11"}
  es6.array.find-index {"ie":"11"}
  es6.array.fill {"ie":"11"}
  es6.array.iterator {"ie":"11"}
  es6.number.is-finite {"ie":"11"}
  es6.number.is-integer {"ie":"11"}
  es6.number.is-safe-integer {"ie":"11"}
  es6.number.is-nan {"ie":"11"}
  es6.number.epsilon {"ie":"11"}
  es6.number.min-safe-integer {"ie":"11"}
  es6.number.max-safe-integer {"ie":"11"}
  es6.math.acosh {"ie":"11"}
  es6.math.asinh {"ie":"11"}
  es6.math.atanh {"ie":"11"}
  es6.math.cbrt {"ie":"11"}
  es6.math.clz32 {"ie":"11"}
  es6.math.cosh {"ie":"11"}
  es6.math.expm1 {"ie":"11"}
  es6.math.fround {"ie":"11"}
  es6.math.hypot {"ie":"11"}
  es6.math.imul {"ie":"11"}
  es6.math.log1p {"ie":"11"}
  es6.math.log10 {"ie":"11"}
  es6.math.log2 {"ie":"11"}
  es6.math.sign {"ie":"11"}
  es6.math.sinh {"ie":"11"}
  es6.math.tanh {"ie":"11"}
  es6.math.trunc {"ie":"11"}
  es7.array.includes {"ie":"11"}
  es7.object.values {"safari":"10","ie":"11"}
  es7.object.entries {"safari":"10","ie":"11"}
  es7.object.get-own-property-descriptors {"safari":"10","ie":"11"}
  es7.string.pad-start {"ie":"11"}
  es7.string.pad-end {"ie":"11"}
  web.timers {"safari":"10","ie":"11"}
  web.immediate {"safari":"10","ie":"11"}
  web.dom.iterable {"safari":"10","ie":"11"}

However, at runtime, I still get the error on IE11 when I call the .find() method on an array.

Anything I can do to double check to make sure the polyfills are injected correctly?

bug

Most helpful comment

The only fix I have is adding a custom layout.js and adding
<script src='https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.23.0/polyfill.min.js' />

All 34 comments

The only fix I have is adding a custom layout.js and adding
<script src='https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.23.0/polyfill.min.js' />

@arunoda We've seen this before right 🤔

As a hot-fix you could do this:

import 'core-js/fn/array/find'

const test = ['hi', 'there'].find(item => item === 'hi')

export default () => (
  <div>{test}, welcome to next.js!</div>
)

Let me see what's going on here.

I checked this with a normal babel app and the behaviour is the same.
You need to add the polyfill as I mentioned above.

So, I'm closing this since it's not exactly a Next specific issue.

But I open to more suggestions.
Feel free to re-open.

@arunoda I tried this hotfix with import 'core-js/fn/array/find' inside the _document.js to have it fixed for all files but it didn't work out for IE11.

I had to go with the solution to include it like this:
<script src='https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/6.23.0/polyfill.min.js' />

I'm using Next.js V3.0.6.

Any Idea how i could solve this in a nicer way?

Hey, all.
I've experimented with the entry-property in next.config.js.
This is what I've got
(according to https://github.com/zeit/next.js/blob/master/server/build/webpack.js#L42):

module.exports = {
  // eslint-disable-next-line no-unused-vars
  webpack(config, _) {
    const entry = async () => {
      const resolvedEntry = await config.entry()
      const entryWithPolyfill = Object.assign(
        { 'babel-polyfill': ['babel-polyfill'] },
        resolvedEntry
      )
      // console.log(entryWithPolyfill)
      return entryWithPolyfill
    }
    return Object.assign(
      config,
      entryWithPolyfill
    )
  }
}

Sadly this file won't be transpiled by babel, which is why it does not work yet.

Best thing would be to include babel-polyfill in Next's webpack config? It is quite common to include it.

@arunoda what do you think?

any updates on this? Including the polyfill is not the best solution

Also interested in this 🤔

I fixed this importing babel polyfills:

import 'babel-polyfill';

Importing the entire babel-polyfill is extremely wasteful and would be a bad default for next.js, imho. It adds 87kb to the bundle no matter if you actually need any of the polyfilled features or not.

@sholzmayer where did you use import 'babel-polyfill';. I tried in the _document.js but it didn't help

@klaemo so what's your suggestion?

Adding transform-runtime to .babelrc plugins seems to do it for me. We are developing an app for Opera 36 which doesn't have Object.entries built in.

"plugins": [
    "transform-runtime"
]

@hugotox as an app developer you could use https://polyfill.io to only load the polyfills needed or you do that manually. In our app we have a polyfills.js that looks something like this:

// Language features presented by https://github.com/zloirock/core-js
import 'core-js/fn/object/assign'
import 'core-js/fn/string/ends-with'
import 'core-js/fn/string/starts-with'
import 'core-js/fn/string/includes'
import 'core-js/fn/array/includes'
import 'core-js/fn/weak-map'

// browser features
import 'raf/polyfill'
import 'isomorphic-fetch'
import 'js-polyfills/url'

Alternatively, nextjs could import and bundle all the polyfills it needs from core-js.

@igimanaloto this solution worked for me

I also use transform-runtime plugin but I do get the error on IE for some reason.

{
  "plugins": [
    "source-map-support",
    "transform-runtime"
  ],
  "presets": [
    ["env", {
      "targets": {
        "node": "6.10"
      }
    }],
    ["stage-3"],
    [
      "next/babel",
      {
        "styled-jsx": {
          "optimizeForSpeed": true,
          "vendorPrefixes": true,
          "sourceMaps": true,
          "plugins": [
            "styled-jsx-plugin-sass"
          ]
        }
      }
    ]
  ]
}

@bliitzkrieg Don't import babel-polyfill in _document.js, because _document.js is only rendered on the server.

Usually, it's recommended to include it in your layout, basically any file that is loaded by all pages will do fine.

Update: Fixed my example for IE 10, 11: changed core-js/library/fn/object/assign dependency in client/polyfill.js to core-js/fn/object/assign (how @klaemo had it—missed that!)


Here's a Dockerized next 5.1.0 attempt to employ a combination of the approach indicated by @klaemo above and an official example, canary/examples/with-polyfills:

[Original question] What is the usage of core-js in my client/polyfills.js file that gets me IE11? (I might expect the approach to proceed from an import that covers everything IE11 is missing and then gradually winnows down the range to just those items the app needs.)

Here's the initial result I checked out the result on a few OS + browser combinations (on Browserstack) and it fails when it was failing on Windows 10 + IE11 (shown below), and maybe other IE combinations.

screen shot 2018-04-21 at 3 49 31 pm

I was trying to run next 5.1.0 on chrome 43 with a custom server, .babelrc and webpack config. import 'core-js/fn/object/assign'; did the trick.

Seems like this bug still exists! I am facing the same issue in IE 11 and none of the solutions is helping. Problems seems to be ansi-regex package which uses a arrow function and this being a dependency of next.js.

@arunoda @timneutkens can we re-open this issue?

Yes still exists. I’m using yarn resolutions to downgrade

import 'core-js/fn/object/assign' worked for me as well.

Had to add core-js first (yarn add core-js) -- of course.

I found this helpful: https://github.com/aspnet/JavaScriptServices/wiki/Supporting-Internet-Explorer-11-(or-older)

Please add an official documentation about ES6 transpilation for node modules.

here is a workaround but this bug has to be reopened. @arunoda

i had errors with Object.assign, String.endsWith on ie11 (on [email protected])

const {basedir} = require('./server/config');

// polyfills required for non-evergreen browsers (mainly ie)
const polyfills = [
'core-js/fn/object/assign',
'core-js/fn/string/ends-with',
'core-js/fn/string/starts-with',
'core-js/fn/string/includes',
'core-js/fn/array/includes',
'core-js/fn/weak-map',
];

module.exports = {
  webpack: (config, {dev, isServer}) => {
    const originalEntry = config.entry;
    if (!isServer) {
      config.entry = async () => {
        const entries = await originalEntry();
        Object.values(entries).forEach(entry => {
          entry.unshift(...polyfills);
          if (dev) {
            entry.unshift('eventsource-polyfill');
          }
        });
        return entries;
      };
    }

    return config;
  },
};

actually i sometimes get

Cannot redefine non-configurable property 'endsWith'

I followed this example to include polyfills.
For IE11 to work, I had to include these in my client/polyfills.js:

import 'core-js/es6/map';
import 'core-js/es6/set';

import 'core-js/fn/object/assign';
import 'core-js/fn/string/ends-with';
import 'core-js/fn/string/starts-with';
import 'core-js/fn/string/includes';
import 'core-js/fn/array/includes';
import 'core-js/fn/array/find';

import 'core-js/fn/number/is-finite';

I am not sure whenever there are some libraries that e.g. needed isFinite, but my app is pretty minimal.

This works, but is very cumbersome to figure out what polyfills that are actually needed.

anyone knows what polyfill is requiired to get the class syntax working in IE11?

class Foo extends ...

in your polyfills uncomment 'import 'core-js/es6/object';' line

I followed the example you mentioned @peec and it worked for me.

@peec is this the expected behavior, though? Why would I need to re-polyfill something that was inlcluded?

Was this page helpful?
0 / 5 - 0 ratings