Babel 6中regeneratorRuntime未定义

827

我正在尝试在Babel 6上从头开始使用async/await,但是我遇到了regeneratorRuntime未定义的问题。

.babelrc 文件

{
    "presets": [ "es2015", "stage-0" ]
}

package.json文件

"devDependencies": {
    "babel-core": "^6.0.20",
    "babel-preset-es2015": "^6.0.15",
    "babel-preset-stage-0": "^6.0.15"
}

.js 文件

"use strict";
async function foo() {
  await bar();
}
function bar() { }
exports.default = foo;

不使用async/await正常运行。有什么想法我做错了吗?


3
babel-polyfill 是您所需要的。 - Ronnie Royston
babel-polyfill已于7.4版本被弃用;这篇更新的Stack Overflow帖子描述了迁移过程。 - JWCS
对于使用较新版本的 Babel 和 Node 的人:https://dev59.com/Y6rka4cB1Zd3GeqPi8ZG#62254909 - Mon
babel预设环境并没有做它所声称的事情:https://github.com/babel/babel/issues/7619#issuecomment-375430112 - aderchox
48个回答

757

babel-polyfill(自Babel 7.4开始已不建议使用)是必需的。你还必须安装它才能让async/await工作。

npm i -D babel-core babel-polyfill babel-preset-es2015 babel-preset-stage-0 babel-loader

package.json

"devDependencies": {
  "babel-core": "^6.0.20",
  "babel-polyfill": "^6.0.16",
  "babel-preset-es2015": "^6.0.15",
  "babel-preset-stage-0": "^6.0.15"
}

.babelrc

{
  "presets": [ "es2015", "stage-0" ]
}

.使用async/await的.js示例代码

"use strict";

export default async function foo() {
  var s = await bar();
  console.log(s);
}

function bar() {
  return "bar";
}

在启动文件中

require("babel-core/register");
require("babel-polyfill");
如果你正在使用 webpack,则需要在webpack配置文件(通常是webpack.config.js)的entry数组中将其作为第一个值,如@Cemen的评论所述:
module.exports = {
  entry: ['babel-polyfill', './test.js'],

  output: {
    filename: 'bundle.js'       
  },

  module: {
    loaders: [
      { test: /\.jsx?$/, loader: 'babel', }
    ]
  }
};

如果您想使用Babel运行测试,则请使用:

mocha --compilers js:babel-core/register --require babel-polyfill

83
使用babel和webpack时很重要:不要使用无效的require("babel-polyfill"),而是将"babel-polyfill"添加到配置文件的entry中,像这样:entry: ["babel-polyfill", "src/main.js"]。 这对我很有效,包括在带有HMR的webpack-dev-server中使用。 - Cemen
6
我尝试使用babel6和async来运行我的mocha测试,并且我不得不在npm测试运行器配置中添加--require babel-polyfill。 - arisalexis
13
babel-register 是用来做什么的? - trusktr
6
如果你使用webpack,就需要将devDependency作为依赖项,因为webpack会在运行前“编译”文件。如果你不使用webpack,并且需要使用babel,则需要将其作为dependency - BrunoLM
5
输出文件会变得非常大,最好只使用必需的内容而不是直接使用babel-polyfill。 - Inanc Gumus
显示剩余18条评论

439

注意 如果您使用的是babel 7,则该软件包已更名为@babel/plugin-transform-runtime

除了polyfill外,我还使用babel-plugin-transform-runtime。这个插件被描述为:

将helpers和builtins引用external化,自动填充代码而不污染全局变量。但这实际上意味着什么呢?基本上,您可以无缝地使用内置函数(如Promise,Set,Symbol等)以及使用所有需要polyfill的Babel功能,而不会污染全局变量,使其非常适合库。

它还包括对ES 6的async/await以及其他内置的支持。

$ npm install --save-dev babel-plugin-transform-runtime
.babelrc文件中,添加运行时插件。
{
  "plugins": [
    ["transform-runtime", {
      "regenerator": true
    }]
  ]
}

11
我不需要 babel-runtime 就能让 async await 正常工作。这句话正确吗?编辑:我在服务器端运行代码。 :) - GijsjanB
9
如果您能够在没有babel-runtime的情况下使用它,那是因为它已经在您的依赖树中了。因此,请注意,如果您正在编写一个库,并且babel-runtime作为开发依赖项出现,则可能不会提供给您的用户。您将需要将其作为普通依赖项包含在发布版中。 - neverfox
29
只需要使用 babel-plugin-transform-runtime 就可以了,非常好用。 - saike
14
这个解决方案不太好,因为它需要额外的 Browserify 或 Webpack 任务来扩展 transform-runtime 插件添加的 require 调用。 - Finesse
23
请注意,对于Babel 7,您需要运行npm install --save-dev @babel/plugin-transform-runtime - Andrey Semakin
显示剩余9条评论

337

Babel 7用户

我在使用Babel 7时遇到了一些问题,因为大多数信息都是针对早期的Babel版本。对于Babel 7,请安装这两个依赖项:

npm install --save @babel/runtime 
npm install --save-dev @babel/plugin-transform-runtime

同时,在.babelrc文件中添加:

{
    "presets": ["@babel/preset-env"],
    "plugins": [
        ["@babel/transform-runtime"]
    ]
}

9
文档中展示了使用"plugins": ["@babel/plugin-transform-runtime"],而不是这里的"plugins": [["@babel/transform-runtime"]]。插件名称不同,两者都能正常工作。但哪个是正确的? - kyw
15
当按照这种方法操作时,我遇到了“require未定义”的错误提示。 - Batman
1
@kyw 最好始终遵循文档 - 除了约定俗成之外没有任何区别。 - Matt Shirley
6
@babel/transform-runtime添加到插件中会导致“exports未定义”的错误。我将其更改为以下内容,以使Babel7中的async函数正常工作:["@babel/plugin-transform-runtime", { "regenerator": true } ] - Hari
1
我正在使用Babel 7.4.4,这个答案对我有用。 - Ryan Shillington
显示剩余5条评论

122

更新

如果您将目标设置为Chrome,则它可以正常工作。但是对于其他目标,可能无法正常工作,请参考:https://github.com/babel/babel-preset-env/issues/112

因此,这个答案并不完全适合原问题。我将其保留在此处,以供参考babel-preset-env

一个简单的解决方案是在代码开头添加import 'babel-polyfill'

如果您使用webpack,一个快速的解决方案是按照下面所示添加babel-polyfill

entry: {
    index: ['babel-polyfill', './index.js']
}

我相信我已找到了最新的最佳实践。

请查看此项目:https://github.com/babel/babel-preset-env

yarn add --dev babel-preset-env

请将以下内容用作您的babel配置:

{
  "presets": [
    ["env", {
      "targets": {
        "browsers": ["last 2 Chrome versions"]
      }
    }]
  ]
}

那么您的应用程序应该可以在 Chrome 浏览器的最后两个版本中使用。

您还可以将Node设置为目标或根据https://github.com/ai/browserslist调整浏览器列表

告诉我什么,不要告诉我如何做。

我真的很喜欢babel-preset-env的理念:告诉我您想要支持哪个环境,不要告诉我如何支持它们。这就是声明式编程的美妙之处。

我已经测试过asyncawait,并且它们确实起作用。我不知道它们是如何工作的,而且我真的不想知道。我想把时间花在自己的代码和业务逻辑上。感谢babel-preset-env,它让我从 Babel 配置地狱中解放了出来。


3
确实有效。唯一的缺点是 babel-preset-env 拉取了一堆依赖项,但我认为这是值得的。我也喜欢声明式风格。 此外,yarn install 现在变成了 yarn add - Roman Usherenko
1
@gargantuan 是的,它确实有这个功能。 - Tyler Liu
3
如果你想要支持旧版浏览器或 Node.js 版本,这并不是一个解决方案。 - Rohan Orton
3
请注意,如果您的代码需要在IE11中运行,则此推荐解决方案将无法使用。 - Maurice
15
为什么这个有那么多点赞?这只能够工作是因为它不再转换async/await,因此不需要regeneratorRuntime,并且因为它没有被转换,所以它不能在不支持它的浏览器上运行。 - Shikyo
显示剩余8条评论

92

更新: Babel 7 post还提供了更深入的答案。


Babel 7.4.0或更高版本(core-js 2 / 3)

Babel 7.4.0开始,@babel/polyfill已被 弃用

一般来说,有两种安装polyfills/regenerator的方式:通过全局命名空间(选项1)或作为ponyfill(选项2,无全局污染)。


选项1: @babel/preset-env

presets: [
  ["@babel/preset-env", {
    "useBuiltIns": "usage",
    "corejs": 3, // or 2,
    "targets": {
        "firefox": "64", // or whatever target to choose .    
    },
  }]
]

将会根据你的target自动使用regenerator-runtimecore-js,不需要手动导入任何内容。别忘了安装运行时依赖:

npm i --save regenerator-runtime core-js

或者,设置useBuiltIns: "entry"并手动导入:

import "regenerator-runtime/runtime";
import "core-js/stable"; // if polyfills are also needed

选项2: 使用@babel/runtime@babel/transform-runtime

此选项不会污染全局作用域,适用于库。

{
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "regenerator": true,
        "corejs": 3 // or 2; if polyfills needed
        ...
      }
    ]
  ]
}

npm i -D @babel/plugin-transform-runtime
npm i @babel/runtime

如果使用了corejs填充,你需要将@babel/runtime替换为@babel/runtime-corejs2(对于"corejs": 2)或@babel/runtime-corejs3(对于"corejs": 3)。

6
这对我进行Node.js构建很有帮助。翻译内容: "presets": [ [ "@babel/preset-env", { "targets": { "esmodules": true } } ] ] - Smolin Pavel
3
我知道了,但为了帮助其他人,这应该是正确的答案。最好的祝福! - pablito91
1
请注意,如果使用值为23corejs选项,则应使用@babel/runtime-corejs2@babel/runtime-corejs3。文档中已经提到了这一点:https://babeljs.io/docs/en/babel-plugin-transform-runtime#corejs - Robin-Hoodie
1
感谢@Robin-Hoodie,我更新了答案的最后一部分,以便在这个主题上更清晰明了。 - ford04

57

如果您不需要babel-polyfill提供的所有模块,您可以在webpack配置中仅指定babel-regenerator-runtime

module.exports = {
  entry: ['babel-regenerator-runtime', './test.js'],

  // ...
};

使用webpack-dev-server和HMR时,这样做可以大大减少每次构建需要编译的文件数量。该模块作为babel-polyfill的一部分安装,因此如果您已经安装了该模块,那么就没问题了;否则,您可以使用 npm i -D babel-regenerator-runtime 单独安装它。


这似乎是最方便的解决方案。然而,大多数浏览器支持生成器,因此这个解决方案可能不是最优的。请参见:http://blogs.candoerz.com/question/213492/babel-plugin-transform-async-to-module-method-without-regenerator.aspx - Kitanotori
如果你不使用webpack呢? - Batman
太棒了。谢谢你。 - Darren Cooney

42

我的简单解决方案:

npm install --save-dev babel-plugin-transform-runtime
npm install --save-dev babel-plugin-transform-async-to-generator

.babelrc

{
  "presets": [
    ["latest", {
      "es2015": {
        "loose": true
      }
    }],
    "react",
    "stage-0"
  ],
  "plugins": [
    "transform-runtime",
    "transform-async-to-generator"
  ]
}

1
你的插件中缺少“transform-async-to-generator”。为了使它正常工作,我不得不把它也加上。 - GabrielBB
@GabrielBB 我已经编辑了这篇文章,所以它是一个完整的例子。 - webnoob
2
需要使用 loose: true 吗? - Tom Söderlund
2
当我使用它时,它会向我的文件添加 require,但在浏览器中 require 是未定义的。 - Batman
不需要使用 loose: true。你真正需要的是在 .babelrc 文件中加入以下内容: { "presets": ["es2015", "react", "stage-2"], "plugins": [ "transform-runtime", "transform-async-to-generator" ] } - Efe Ariaroo

42

当没有正确使用Babel插件时,使用async/await函数会导致此错误。截至2020年3月,以下应该是你需要做的全部内容。(在Babel中,@babel/polyfill和很多被接受的解决方案已经被弃用。 在Babel文档中了解更多信息。)

在命令行中键入:

npm install --save-dev @babel/plugin-transform-runtime
在您的babel.config.js文件中,添加此插件@babel/plugin-transform-runtime。注意:下面的示例包括我最近为一个小型React / Node / Express项目使用的其他预设和插件:
module.exports = {
  presets: ['@babel/preset-react', '@babel/preset-env'],
  plugins: ['@babel/plugin-proposal-class-properties', 
  '@babel/plugin-transform-runtime'],
};

总是让我惊讶的是开发人员有多么懒。Babel 的开发人员决定弃用某些功能,他们可能预计到这会成为一个问题。为什么不让人们知道最可能的意图以及他们该如何修复它呢?但是没有,让我们只显示一些对新手绝对没有用处的消息。 - Pavel Voronin
6
对我来说效果很好。我非React项目的.babelrc文件看起来是这样的:{ "presets": [ "@babel/preset-env" ], "plugins": [ "@babel/plugin-transform-runtime" ] } - Anthony
我收到一个错误,指出属性“presets”无效。 - viv
1
它告诉我 Uncaught ReferenceError: require is not defined - Thielicious
谢谢!终于有一个答案不使用废弃的@babel/polyfill。当我尝试在我的测试中使用async/await时,这对我很有效。 - CodeConnoisseur

24

babel-regenerator-runtime现在已弃用, 取而代之应该使用regenerator-runtime

要在webpackbabel v7中使用运行时生成器:

安装regenerator-runtime

npm i -D regenerator-runtime

然后在webpack配置中添加:

entry: [
  'regenerator-runtime/runtime',
  YOUR_APP_ENTRY
]

这应该是被接受的答案,babel-polyfill添加了太多其他的东西。 - Shikyo
工作完美,非常感谢。 - Leandro William
1
这种方法总是包含运行时。我认为这违背了@babel/preset-envuseBuiltIns的目的,即根据您的目标浏览器动态插入运行时。 - kyw

20

根据以下示例更新您的.babelrc文件,它将正常工作。

如果您使用的是@babel/preset-env

{
  "presets": [
    [
      "@babel/preset-env", {
        "targets": {
          "node": "current"
        }
      }
    ]
  ]
}
or if you are using babel-preset-env package

{
  "presets": [
    [
      "env", {
        "targets": {
          "node": "current"
        }
      }
    ]
  ]
}

4
请您解释一下您的答案,"node": "current" 是什么意思? - lazyCoder
我也想知道这是做什么的,以及它是否是一个推荐的解决方案 - 也就是说,它不会危及任何东西,并且是“未来证明”的(尽可能地)。targets似乎是指这个您支持/针对项目的环境,而targets.node这个如果您想要编译当前节点版本,可以指定“node”:true或“node”:“current”,这将与“node”:process.versions.node相同 - user1063287
顺便说一句,我使用了答案中定义的第二个代码块(并在此过程中删除了“stage-0”),然后regenerator错误消失了。 - user1063287
2
@BunkerBoy 为了方便起见,您可以使用“node”:“current”仅包括运行Babel所使用的Node.js版本所需的必要填充和转换。 - Zero
那么我不需要安装 polyfill 吗? - lazyCoder
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接