【babel7.4】Uncaught ReferenceError: regeneratorRuntime is not defined【webpack】


babel / webpack 使用時にUncaught ReferenceError: regeneratorRuntime is not definedと出力された場合の対処方法

babelのバージョンによって、対処方法が違うことがわかった。

Error

request.js?2ade:1 Uncaught ReferenceError: regeneratorRuntime is not defined
    at eval (request.js?2ade:1)
    at eval (request.js?2ade:1)
    at Module../src/request.js (bundle.js:83)
    at __webpack_require__ (bundle.js:523)
    at eval (index.js:3)
    at Module../src/index.js (bundle.js:65)
    at __webpack_require__ (bundle.js:523)
    at bundle.js:585
    at bundle.js:588

↓みたいなコードでasyncがわからんって言われるやつ。

const getCountry = async (code='JP') => {

※babelさんはIEやらなんやらの互換性のないブラウザで該当プログラムを動かすことができるようにしてくれる方なんだけど、互換方法にはいろいろあって、非同期のasyncなどは専用の翻訳機(意訳)を用意する必要がある。
babelさんのバージョンによって、推奨される翻訳機の設定内容や名前が変わっているので、設定方法もいろいろあるという訳。

babel7.3以前はbabel-polyfillをインストールすれば良い。

とはいえ、これからどんどん非推奨になると思うが。
babel-polyfill

npm install --save @babel/polyfill
webpack.config.js
module.exports = {
  entry: './src/index.js',

webpackでは上記のようにentryしている箇所のtopでimportすれば良い。

index.js
import "@babel/polyfill";

babel7.4以降はbabel-polyfillは非推奨らしい。

package.json
"@babel/core": "^7.12.3"

🚨Babel7.4.0の時点で、このパッケージは非推奨にcore-js/stableなり、regenerator-runtime/runtime(ECMAScript機能をポリフィルするために)直接含めることと(トランスパイルされたジェネレーター関数を使用する必要がある)ことが優先されます。

1.@babel/preset-env をインストール
2.webpack.config.jsに記入
3.index.jsにimport

npm install -D @babel/preset-env
npm install core-js
webpack.config.js
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
index.js
import "core-js/stable";
import "regenerator-runtime/runtime";

確か、これで動いたと思うけど、これで動作しなかったら、下記2つをインストールする。

npm install -S core-js@3
npm install -S regenerator-runtime

babel7.4以降でもimportしたくない。

7.3以前はimportしなくても良さげな設定たくさん出てくるのに、7.4以降はimportするみたいな記事ばっかりでてきたので、なんかやり方があるはず(ついでにbabelとwebpackについても勉強したい)と重い調査。

正直、webpackもbabelもほぼ知らない状態でドキュメントを読み漁ったので不要なものもある気がする。

npm install -S @babel/runtime
npm install -D @babel/plugin-transform-runtime
npm install --save-dev @babel/runtime-corejs3

たぶんnpm install -S @babel/runtimeは不要で、.babelrcファイルに記載したcorejsの値がnoneの時、2の時、3の時と使い分けるためのnpmパッケージになる(はず)

.babelrc
{
    "presets": [
        ["@babel/preset-env"],
    ],
    "plugins": [
        ["@babel/plugin-transform-runtime", { "corejs":3 }]
    ]
}

結局、polyfilが非推奨になった理由は、対象ブラウザの範囲が広がれば広がるほど、babelの仕事が多くなる。そうするとbabelの変換時に負荷も高くなる。
babelの翻訳時の処理時間や負担を減らそうぜってことだと思っている。
runtimeはpolyfilを含む訳ではなく、helperにより動作しているcorejsを自分で選択して設定することができるので、負担が軽くなる仕組みらしい。
だから、たぶんこの設定であってるんじゃないかなぁ?と思っている。

いろいろ設定したけど、もしかしたら、webpack initで解決した問題かもしれない。

そんなことよりも、core-jsの記事が衝撃的だった。
私たちは先達のエンジニアにとても感謝しなければならないと思った。

環境(おまけ)

node --version
v12.18.4
package.json
{
  "main": "index.js",
  "scripts": {
    "build": "webpack --watch",
    "start": "webpack serve --mode development",
  },
  "devDependencies": {
    "@babel/plugin-transform-runtime": "^7.12.1",
    "@babel/runtime-corejs3": "^7.12.5",
    "babel-loader": "^8.1.0",
    "source-map-loader": "^1.1.2",
    "webpack-cli": "^4.2.0",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "@babel/core": "^7.12.3",
    "@babel/preset-env": "^7.12.1",
    "@babel/runtime": "^7.12.5",
    "@webpack-cli/init": "^1.0.3",
    "babel-cli": "^6.26.0",
    "babel-plugin-syntax-dynamic-import": "^6.18.0",
    "babel-preset-env": "^1.7.0",
    "core-js": "^3.6.5",
    "webpack": "^5.4.0"
  }
}
webpack.config.js
const path = require('path')

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'public/scripts'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env']
          }
        }
      }
    ]
  },
  devServer: {
    open: true,
    contentBase: path.resolve(__dirname, 'public'),
    publicPath: '/scripts/'
  },
  devtool: 'eval-source-map',
}

参考記事

babel/polyfill
babel/preset-env
7.4.0リリース:core-js 3、静的プライベートメソッドおよび部分適用
@babel/plugin-transform-runtime
babel/option
@babel/runtime-corejs3
Babel7.4で非推奨になったbabel/polyfillの代替手段と設定方法
Babel 7 の主な変更点まとめ
core-js
core-jsがメンテされていない理由→プロジェクトは継続する
Babel7にアップグレード
Babel 7.4でcore-js系の「Module not found」が出た場合の対策(babel7.4,webpack4)
@babel/preset-envのuseBuiltInsを使ってpolyfillする
@babel/plugin-transform-runtime で Promise が変換されずハマった
webpack/entry point
webpack/babel-loader
webpack入門
webpack init で webpack.config.js を自動生成しよう