Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Example of using babel-polyfill #2060

Closed
pencilcheck opened this issue May 24, 2017 · 16 comments
Closed

Example of using babel-polyfill #2060

pencilcheck opened this issue May 24, 2017 · 16 comments

Comments

@pencilcheck
Copy link
Contributor

After installing babel-polyfill, in next.config.js


module.exports = {
  webpack: (config, { dev }) => {
    var oldEntry = config.entry;
    config.entry = function () {
      return oldEntry().then(function (entries) {
        entries['main.js'].unshift('babel-polyfill');
        return entries;
      });
    }

    return config;
  }
};

@arunoda
Copy link
Contributor

arunoda commented May 25, 2017

We use this automatically as you use features which needs a polyfill. You don't need to use it manually.

@arunoda arunoda closed this as completed May 25, 2017
@pencilcheck
Copy link
Contributor Author

pencilcheck commented May 25, 2017

Well, the version I was on v2.4.0 doesn't work (on IE 11, etc) if I didn't include the script I wrote above. I got errors for null calling on "includes" methods etc.
I assume that means polyfill either isn't included automatically or what it was there didn't work at all.

@arunoda
Copy link
Contributor

arunoda commented May 26, 2017

@pencilcheck I assume this is related to a module in your app. It doesn't come with a polyfill. In that case you need to use it.
But including the whole babel-polyfill is not a good option. It's huge.

May be you can add the exact polyfill you need. Use core-js
That's what's inside babel-polyfill

@joaovieira
Copy link

joaovieira commented Apr 28, 2018

Things have come a long way. babel-polyfill now plays well with babel-preset-env so you can include only the polyfills for your target environments/browsers. To do that:

// next.config.js
module.exports = {
  webpack: (config) => {
    // Unshift polyfills in main entrypoint.
    const originalEntry = config.entry;
    config.entry = async () => {
      const entries = await originalEntry();
      if (entries['main.js']) {
        entries['main.js'].unshift('./polyfills.js');
      }
      return entries;
    };
  
    return config;
  }
}
// polyfills.js
import 'babel-polyfill';

Babel 6

// .babelrc
{
  "presets": [
    [
      "next/babel",
      {
        "preset-env": {
          "targets": {
            "browsers": "defaults"
          },
          "useBuiltIns": true
        }
      }
    ]
  ]
}

Babel 7

// .babelrc (Babel 7)
{
  "presets": [
    [
      "next/babel",
      {
        "preset-env": {
          "useBuiltIns": "usage"
        }
      }
    ]
  ]
}
// .browserslistrc
defaults

You still need a separate polyfills.js file with the import statement, as simply unshifting babel-polyfill as the original post will include all the polyfills.

Would be good to consider this as default in Next though.

@vjpr
Copy link

vjpr commented May 5, 2018

I just want to leave a note here that after upgrading to Next 6, after every navigation that required a server build, HMR informed me that "The following modules couldn't be hot updated: (Full reload needed)" because - undefined module could not be hot replaced.

screen shot 2018-05-04 at 11 29 16 pm

I noticed that multiple babel-polyfill's were being added to the bundle (by console.log the moduleMap in webpack-hot-middleware/client.js) each time a page needed to be built.

I removed the babel-polyfill code and the issue went away. So maybe something to be cautious of.

@notatestuser
Copy link
Contributor

notatestuser commented May 14, 2018

@joaovieira a couple of comments on that:

useBuiltins does not appear to accept a value of true now, see the error below:

Module build failed: Invariant Violation: [BABEL] ~/pages/_error.js: Invalid Option: The 'useBuiltIns' option must be either
    'false' (default) to indicate no polyfill,
    '"entry"' to indicate replacing the entry polyfill, or
    '"usage"' to import only used polyfills per file (While processing: "~/node_modules/next/babel.js$0")
    at invariant (~/node_modules/invariant/invariant.js:40:15)
    at validateUseBuiltInsOption (~/node_modules/next/node_modules/@babel/preset-env/lib/normalize-options.js:130:26)

also there seems to be no need to hack the webpack entries, you can use the clientBootstrap in next.config.js:

exports = module.exports = {
   // ...
   clientBootstrap: [path.join(__dirname, './app/polyfills.js')]
   // ...
};

with the same content in polyfills.js as in your example.

@timneutkens
Copy link
Member

timneutkens commented May 14, 2018

clientBootstrap is not part of the Next.js codebase at this point.

@yves-s
Copy link

yves-s commented May 14, 2018

To add IE11 Array.includes support I added includes as polyfill from core-js. But now I have the same issue as @vjpr.

screen shot 2018-05-14 at 14 12 45

If I just removed the polyfill part from the config it works as expected and doesn't reloads at every page navigation.

I don't get it yet how to fix it. Following some code example:

next.config.js

module.exports = {
    webpack: function(cfg) {
        const originalEntry = cfg.entry;

        cfg.entry = async() => {
            const entries = await originalEntry();

            if(entries['main.js']) {
                entries['main.js'].unshift('./src/polyfills.js');
            }

            return entries;
        };

        return cfg;
    },
};

src/polyfill,js

/* eslint no-extend-native: 0 */
import includes from 'core-js/library/fn/array/virtual/includes';

Array.prototype.includes = includes;

@novascreen
Copy link
Contributor

Facing the same issue, for now I conditionally only add my polyfills for production

    webpack: function(cfg, { dev }) {
		if (!dev) {
	        const originalEntry = cfg.entry;
    	    cfg.entry = async() => {
			// ...

@loganwedwards
Copy link

Thanks to @joaovieira for your example. It solved my issue for supporting IE11. If you are on Babel 7 (Next 6.x and beyond), a small change in the preset is required. Here is the updated code (including an example of transpiling a node module that used an arrow function:

This assumes you have a file called polyfills.js that just has a import @babel/polyfill.

const path = require('path')

module.exports = {
  webpack: config => {
    // Unshift polyfills in main entrypoint.
    const originalEntry = config.entry
    config.entry = async () => {
      const entries = await originalEntry()
      if (entries['main.js']) {
        entries['main.js'].unshift('./polyfills.js')
      }
      return entries
    }
    // This lib has an arrow fn causing IE11 to explode
    config.module.rules.push({
      test: path.resolve('./node_modules/superagent-charset/index.js'),
      loader: 'babel-loader',
      options: {
        babelrc: false,
        cacheDirectory: true,
        presets: ['@babel/preset-env'],
      },
    })

    return config
  },
}

@chrisjcodes
Copy link

chrisjcodes commented Nov 28, 2018

Are the imports in polyfills.js being transpiled by babel?
I'm including a polyfill for Object proxy https://github.com/GoogleChrome/proxy-polyfill
and IE is throwing on the template string in one of the errors. I confirmed that preset-env is applying the babel plugin for converting template strings.

@ishwinder
Copy link

Does this solution works only for the client side code ? I keep on getting regeneratorRuntime is not defined if I use async/await on server side code.

@rap2hpoutre
Copy link

With babel 7 and nextjs 7, just add useBuiltIns: "usage" in .babelrc and it works:

module.exports = {
  presets: [
    [
      "next/babel",
      {
        "preset-env": {
          targets: {
            browsers: [">0.03%"]
          },
          useBuiltIns: "usage"
        }
      }
    ]
  ]
};

Source : https://babeljs.io/docs/en/babel-polyfill#usage-in-node-browserify-webpack

@fabb
Copy link
Contributor

fabb commented Feb 7, 2019

Note that this will NOT polyfill anything that node_module dependencies depend on, since it only inserts polyfills for stuff that is babel transformed, and by default node_modules are not babel transpiled when building the client project (which is a good thing).

@rap2hpoutre
Copy link

rap2hpoutre commented Feb 21, 2019

@joaogranado Using your solution with babel 7 gives this error (warning?) on build:

When setting `useBuiltIns: 'usage'`, polyfills are automatically imported when needed.
Please remove the `import '@babel/polyfill'` call or use `useBuiltIns: 'entry'` instead.

I changed "useBuiltIns": "usage" to "useBuiltIns": "entry" and it seems to work, not sure it's the right way though...

@tills13
Copy link
Contributor

tills13 commented Mar 25, 2019

@rap2hpoutre for whatever reason, this solution isn't working for us - still getting Object does not support property or method 'assign' errors in IE 11. Is there anything further we need beyond the configuration change in .babelrc? (the entries business, perhaps?)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests