Merc
Merc

Reputation: 17067

Get rid of "regeneratorRuntime is not defined" without importing the polyfill

I wrote a library of elements, and want to make sure designers can just add the right source file to their HTML pages to start using it. I am creating a bundle using rollup (to roll it up to one file) and babel (to make sure any browser can use it).

My rollup.conf is pretty simple:

import resolve from 'rollup-plugin-node-resolve'
import babel from 'rollup-plugin-babel'
import minify from 'rollup-plugin-babel-minify'

module.exports = [

  // IIFE
  {
    input: './tpe.js',
    output: {
      file: 'distr/tpe.js', // IIFE ONE FILE
      format: 'iife'
    },
    plugins: [resolve({}), babel({})]
  },

  {
    input: './themes/material/material.js',
    output: {
      file: 'distr/material.js', // IIFE ONE FILE
      format: 'iife'
    },
    plugins: [resolve({}), minify({})]
  }
]

Note that ./tpe.js contains a long list of imports:

import './ee-autocomplete-input-spans.js'
import './ee-autocomplete-item-country.js'
import './ee-autocomplete-item-email.js'
import './ee-autocomplete-item-li.js'
import './ee-autocomplete.js'
import './ee-drawer.js'
import './ee-fab.js'
import './ee-header.js'
import './ee-nav-bar.js'
import './ee-network.js'
import './ee-snack-bar.js'
import './ee-tabs.js'
...

My babel.conf.js is even simpler:

module.exports = function (api) {
  api.cache(true)

  const presets = [
    [
      '@babel/env', {
        modules: false,
        exclude: [],
        targets: {
          ie: "9"
        }
      }
    ]
  ]
  const plugins = []

  return {
    presets,
    plugins
  }

This is all fine, except that I have to ask my users to do this:

<script src="https://unpkg.com/@babel/polyfill/dist/polyfill.min.js"></script>
<script src="./distr/material.js"></script>
<script src="./distr/tpe.js"></script>

<nn-input-text id="input" name="aName"></nn-input-text>

Without that polyfill.min.js, I get the dreaded regeneratorRuntime is not defined.

I spent hours, and hours, and hours trying to make sure that I don't need to ask users to have that polyfill.min.js.

To "fix" the problem, I added this to my ./tpe.js:

import 'regenerator-runtime/runtime'
import './ee-autocomplete-input-spans.js'
import './ee-autocomplete-item-country.js'
import './ee-autocomplete-item-email.js'
import './ee-autocomplete-item-li.js'

This actually allows me to have just this:

<script src="./distr/material.js"></script>
<script src="./distr/tpe.js"></script>

<nn-input-text id="input" name="aName"></nn-input-text>

QUESTIONS:

Results in a lot of warnings. And then if I add an exclude in rollup.conf.js like this:

plugins: [resolve({}), babel({exclude: [/\/core-js\//]}), minify({})]

Things compile, but the result doesn't work (Uncaught SyntaxError: Cannot use import statement outside a module). If I instead do:

    useBuiltIns: "entry",
    corejs: 3

I don't need the "exclude", but it doesn't seem to do anything. Do I actually need the corejs polyfills?

Upvotes: 3

Views: 1544

Answers (1)

seangwright
seangwright

Reputation: 18205

I saw the Github issue you opened and linked to this post.

I have also been trying to diagnose this setup and the problems I've run into trying to configure it.

Checkout this recommended config on the rollup-plugin-babel repo.

I was running into the same issue with regeneratorRuntime is not defined and couldn't figure out why the polyfills weren't being loaded as I hoped/expected.

The key seems to be that 3 plugins are required for this use-case.

// We need all 3 of these to end up with the 'usage'-based babel polyfills

import babel from "rollup-plugin-babel";
import commonjs from "rollup-plugin-commonjs";
import resolve from "rollup-plugin-node-resolve";

export default [
  {
    input: "src/index.js",
    output: {
      file: "dist/index.js",
      format: "iife"
    },
    plugins: [
      resolve(),
      babel({
        exclude: "node_modules/**",
        presets: [
          [
            "@babel/preset-env",
            {
              corejs: 3,
              modules: false,
              useBuiltIns: "usage",
              targets: {
                ie: "11"
              }
            }
          ]
        ]
      }),
      commonjs()
    ]
  }
];

Here's my dependenices from package.json:

  "scripts": {
    "start": "rollup -c --compact --watch"
  }
  "dependencies": {
    "core-js": "^3.3.4",
    "regenerator-runtime": "^0.13.3"
  },
  "devDependencies": {
    "@babel/core": "^7.6.4",
    "@babel/preset-env": "^7.6.3",
    "rollup": "^1.26.0",
    "rollup-plugin-babel": "^4.3.3",
    "rollup-plugin-commonjs": "^10.1.0",
    "rollup-plugin-node-resolve": "^5.2.0",
  }

My output dist/index.js ends up including this assignment for regeneratorRuntime, which wasn't there before I had all 3 of the above rollup plugins:

try {
  regeneratorRuntime = runtime;
} catch (accidentalStrictMode) {
  // This module should not be running in strict mode, so the above
  // assignment should always work unless something is misconfigured. Just
  // in case runtime.js accidentally runs in strict mode, we can escape
  // strict mode using a global Function call. This could conceivably fail
  // if a Content Security Policy forbids using Function, but in that case
  // the proper solution is to fix the accidental strict mode problem. If
  // you've misconfigured your bundler to force strict mode and applied a
  // CSP to forbid Function, and you're not willing to fix either of those
  // problems, please detail your unique predicament in a GitHub issue.
  Function("r", "regeneratorRuntime = r")(runtime);
}

Upvotes: 1

Related Questions