Next.js: Migrate from core-js@2 to core-js@3 in Babel config

Created on 25 Jul 2019  路  21Comments  路  Source: vercel/next.js

Feature request

Is your feature request related to a problem? Please describe.

core-js@3 has been released in March 2019, adding a lot of new features. It's a great time to revamp the Babel config provided by Next.

Describe the solution you'd like

A modern-ish approach to configure Babel.

Describe alternatives you've considered

Got rid of next/babel preset in custom Babel config, adding everything by hand.

Additional context

So, I had this quite straightforward Babel config (.babelrc) for ages:

{
  "plugins": [
    "@babel/plugin-transform-flow-strip-types",
    "babel-plugin-styled-components",
    "inline-react-svg"
  ],
  "presets": [
    "next/babel"
  ]
}

with the following .browserslistrc:

node 10.16
last 4 chrome versions
last 4 firefox versions
last 4 edge versions
last 2 safari versions
ie 11
not dead

and eventually I discovered that the app doesn't work in IE 11. I mean, something worked and something didn't. So I started to dig up to make sure every feature which Internet Explorer 11 is missing is polyfilled.

I checked the next/babel preset and figured out that it contains both @babel/plugin-transform-runtime plugin and @babel/preset-env:

 [
        require('@babel/plugin-transform-runtime'),
        {
          corejs: 2,
          helpers: true,
          regenerator: true,
          useESModules: supportsESM && presetEnvConfig.modules !== 'commonjs',
          ...options['transform-runtime'],
        },
],

Here, the polyfilling is being done by the @babel/plugin-transform-runtime plugin, using core-js@2. But in the age of Babel ^7.4, it's suggested to use @babel/preset-env for that, setting its useBuiltIns and corejs options.

Being unable to use @babel/preset-env and disable @babel/plugin-transform-runtime, I "dissected" the whole next/babel preset and reassembled it in custom .babelrc, excluding some plugins which are irrelevant for my project (like AMP and styled-jsx).

So I ended up with this:

{
  "plugins": [
    "@babel/plugin-transform-flow-strip-types",
    "inline-react-svg"
  ],
  "env": {
    "development": {
      "plugins": [
        "babel-plugin-styled-components",
        "babel-plugin-react-require",
        "@babel/plugin-syntax-dynamic-import",
        "./node_modules/next/dist/build/babel/plugins/react-loadable-plugin",
        "@babel/plugin-proposal-class-properties",
        [
          "@babel/plugin-proposal-object-rest-spread",
          {
            "useBuiltIns": true
          }
        ]
      ],
      "presets": [
        [
          "@babel/preset-env",
          {
            "debug": true,
            "modules": false,
            "exclude": [
              "transform-typeof-symbol"
            ],
            "useBuiltIns": "usage",
            "corejs": "3.1"
          }
        ],
        [
          "@babel/preset-react",
          {
            "development": true
          }
        ]
      ]
    },
    "production": {
      "plugins": [
        "babel-plugin-styled-components",
        "babel-plugin-react-require",
        "@babel/plugin-syntax-dynamic-import",
        "./node_modules/next/dist/build/babel/plugins/react-loadable-plugin",
        "@babel/plugin-proposal-class-properties",
        [
          "@babel/plugin-proposal-object-rest-spread",
          {
            "useBuiltIns": true
          }
        ]
      ],
      "presets": [
        [
          "@babel/preset-env",
          {
            "modules": false,
            "exclude": [
              "transform-typeof-symbol"
            ],
            "useBuiltIns": "usage",
            "corejs": "3.1"
          }
        ],
        "@babel/preset-react"
      ]
    },
    "test": {
      "plugins": [
        "babel-plugin-styled-components",
        "@babel/plugin-proposal-class-properties"
      ],
      "presets": [
        [
          "@babel/preset-react",
          {
            "development": true
          }
        ],
        [
          "@babel/preset-env",
          {
            "targets": "node 10.16",
            "useBuiltIns": false,
            "ignoreBrowserslistConfig": true
          }
        ]
      ]
    }
  }
}

(Note: babel.config.js didn't work for me, so I stayed with the .babelrc for now)

That being said, please consider upgrading the next/babel preset to make sure it's using all the latest/greatest stuff.

Nice project by the way :slightly_smiling_face:.

Most helpful comment

Whit "next": "^9.1.3", I get:
warning next > @babel/runtime-corejs2 > [email protected]: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3 and warning next > styled-jsx > babel-types > babel-runtime > [email protected]: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.

Updating the deps would fix this warning I guess :)

All 21 comments

@Timer @HaNdTriX so Babel guys confirmed, that useBuiltIns and @babel/plugin-transform-runtime are mutually exclusive.

Also, look out for the new useBuiltIns: pure option which will be added to the Babel soon.

Thanks for digging into this @awthwathje! We'll try to update the babel configuration soon.

@Timer great, thanks a lot for the effort. Ping me if you need any help.

@Timer
I was trying to make the bundle size as small as possible (we don't need IE11 at all, and rely on the latest browsers)
our .browserslistrc is

last 2 version
> 2%
maintained node versions
not dead
not ie <= 11
not op_mini all

I moved from core-js@2 to core-js@3 using:

"next/babel", {
  "preset-env": {
    "corejs": 3,
    "useBuiltIns": "entry"
  }
}

And as I understood from the topic the following setting does not work:

"transform-runtime": {
  "corejs": 3
}

For me it just does not finish bundling process at all.
Do you have any suggestions? I assume it makes sense to wait until the support of core-js@3 will be enabled by default, right?

@Carduelis I'm not @Timer, but you are correct: @babel/preset-env's useBuiltIns option and @babel/plugin-transform-runtime are mutually exclusive and should not be used together.

You could use custom Babel config, like I do (it's in the original post), while waiting for the core-js@3 integration into Next.

Whit "next": "^9.1.3", I get:
warning next > @babel/runtime-corejs2 > [email protected]: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3 and warning next > styled-jsx > babel-types > babel-runtime > [email protected]: core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.

Updating the deps would fix this warning I guess :)

image

Can't count how many times i have encountered this crap in the last 6 months...

This is a burden now. Everything moved on to core-js 3 but "next" did not

We're removing core-js being included in Next.js completely in favor of a separate chunk only loaded in older browsers: https://github.com/zeit/next.js/pull/10212

@timneutkens thats great news. Currently there is a experimental: {modern:true} flag, is this one now replaced with the experimental:{polyfillsOptimization: true} flag?

No those 2 are completely separate efforts and do different things.

Btw the message shown by npm is very out of context and needlessly pressing. We never had any issues with core-js@2 and I wish we could instruct npm to not show certain messages when installing Next.js 馃槙

@timneutkens could you point out the difference between them? I thought themodern build is taking care of browser switch between old and new browsers?

  • polyfillsOptimization -> removes core-js from modern browsers and adds all required IE11 polyfills loaded only for older browsers using the nomodule property
  • modern -> preserves for example async/await and other modern language features like const let etc. and loads that only in browsers that support script type="module" and compiles down async/await in a separate bundle and serves that for older browsers using nomodule

@timneutkens when trying to use polyfillsOptimzation it seems I still have to use the react-app-polyfill to get our app to run in IE11.

@timneutkens thanks for the heads up

@lifeiscontent a reproduction would be helpful otherwise it's hard to do anything actionable.

@timneutkens I'll see if I have time to put something together later this week, thanks!

@timneutkens what is the recommended babel.config.js after this changes?

@dohomi no babel config? There's only a few reasons to have it.

@Timer @timneutkens thanks a lot guys, this is super-helpful and now Next.js apps work in IE11 without any additional configuration!

Just wanted to mention, that it worked for me only with [email protected] and not with [email protected]. I bootstrapped the project with create-next-app.

@awthwathje it was not released yet, will be part of 9.3, you can opt-in on stable through:

// next.config.js
module.exports = {
  experimental: { polyfillsOptimization: true }
}

@timneutkens thanks for the clarification, for some reason I thought that the fact that this ticket was closed means that the feature has landed in stable, that is 9.2. My bad.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

olifante picture olifante  路  3Comments

havefive picture havefive  路  3Comments

timneutkens picture timneutkens  路  3Comments

wagerfield picture wagerfield  路  3Comments

jesselee34 picture jesselee34  路  3Comments