Next.js: `babel-runtime` cannot be explicitly included when needed for SSR

Created on 30 Mar 2018  Â·  9Comments  Â·  Source: vercel/next.js

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Repro steps

When using an npm module that requires regeneratorRuntime (part of babel-runtime), I get an error:

regeneratorRuntime is not defined

Makes sense. So I try to define it by placing this at the top of my page .js file:

import 'babel-runtime';
import 'babel-runtime/regenerator';

But the error persists. It seems like I'm not importing the runtime early enough, but I don't know where else to put it. If I move it to _document.js, the same problem occurs.

Ultimately, I just want regeneratorRuntime to be defined on both client and server so I can use a library that expects it. (Many libraries exclude regeneratorRuntime from their bundles because it's oftentimes needed by several dependencies, and it's quite large.)

Is there some straightforward way to do this that I'm missing?

Your Environment

| Tech | Version |
|---------|---------|
| next | 5.1.0 |
| node | 8.9.1 |

All 9 comments

Which npm package is it? Because it should import the runtime itself internally, even if it defines the babel runtime as a peer dependency.

When I'm testing firebase example. When using ES6 functions such as async/await or destructuring assignment ex:Page.getInitialProps = async ({res}) => {....} Server-side error with regeneratorRuntime is not defined

Hi @jaydenseric — I'm experiencing this with fluent.js. (I've opened a parallel issue over there: https://github.com/projectfluent/fluent.js/issues/176)

Best practices dictate that a package should bundle all of its dependencies, and the process of bundling eliminates the concept of 'importing' — you should just get one file with everything in it. As I mentioned in the issue description, package publishers sometimes deviate from this 'best practice' of including 100% of the package's dependencies in the bundle since regenerator-runtime is quite common and large, and it'd be a shame for multiple bundles to carry it along into an app.

It appears that @ismailbaskin found another package that assumes that regenerator-runtime will be included by the app.

I'll continue to push fluent.js to publish a bundle with everything included (including regenerator-runtime), but I'm still quite convinced that Next.js should have a way for the end-developer to force its inclusion as a global.

@jamesreggio best practice for packages is to not bundle, otherwise we would have massive duplication in node_modules. The consumer should tree-shake and minify their app bundle.

I don't think Next.js should encourage or facilitate polluting globals, in your app you can import "regenerator-runtime/runtime" before importing packages that assume the global is present. Better yet, the packages should be patched to do that themselves.

The global scope issue with regenerator-runtime is bad design, and working around it is unpleasant. Babel runtime transform aliases regenerator and uses imports. I don't advise using the runtime transform though, it is also very bloated. Although (I'm pretty sure) importing babel-polyfill would set up the runtime, it is absolutely massive and not suitable for libraries. The ultimate solution is to avoid regenerator altogether; see https://github.com/babel/babel/pull/7076.

A realistic approach for library authors is for the client to not use async/await until Babel has a simple promise based transform, and for the server to use async/await natively without transforms and drop support for legacy Node.js versions.

Fair enough, @jaydenseric — I shouldn't have used an opinionated term like 'best practice'.

The problem remains that some npm modules only provide two methods of import:

  • a transpiled, bundled version via main in package.json
  • unbundled source code via module in package.json

Even though module is a de-facto standard supported in Webpack (and, by extension, Next.js), it still breaks down if the code referenced by module isn't transpiled to a 'compatible' version of JavaScript, because Babel cannot easily be run on the contents of node_modules. (See #706, which has been open for over a year.)

The definition of 'compatible' is defined by the consumer of the package, so if the consumer is targeting ES5 while the package producer targets ES6, the package code still won't run properly. Hence why package developers often include an ES5-compatible bundle. Which returns us to my concrete use case.

in your app you can import "regenerator-runtime/runtime" before importing packages that assume the global is present

The whole point of this issue is _that doesn't work_. If you re-read the issue description, I tried placing these runtime imports at the top of my page and at the top of _document.js — but that doesn't work. The module with the regenerator-runtime dependency is being evaluated before the regenerator-runtime/runtime import.

If there's another place I should be placing the regenerator-runtime/time import, I'm all ears.

@jamesreggio

…some npm modules only provide two methods of import:

  • a transpiled, bundled version via main in package.json
  • unbundled source code via module in package.json

Neither main or module should be bundled or minified, and both should be transpiled. The only difference in contents is that instead of transpiling the module to use CJS, it should contain ESM imports and exports. Emerging best practice for native ESM goes a little further:

{
  "main": "index",
  "module": "index.mjs"
}

This issue does not relate to Next.js and can be closed. The fix for your issues is to fix the broken packages you wish to use by making sure they define all their own dependencies and globals.

Neither main or module should be bundled or minified

I must be living in a very different world ¯_(ツ)_/¯

@jaydenseric Isn't regenerator-runtime or @babel/runtime already bundled with Next.js? I believe one of those two is needed for using async/await, which works by default in Next

@NathanielHill using async/await works by default in Next when in page/component; when put the async/await function (such as getInitialProps) under a custom server.js, the regeneratorRuntime is not defined error came out.

Was this page helpful?
0 / 5 - 0 ratings