引用错误:regeneratorRuntime未定义(但在作用域内工作)

21

我遇到了这个奇怪的情况:

ReferenceError: regeneratorRuntime未定义

...我已经在一个非常简单的设置中复制了这个问题(与相似的SO问题相比),并且还注意到根据是否使用范围会有一些奇怪的行为。

以下代码有效:

'use strict';

require('babel-polyfill');

{  // scope A (if you remove it you observe different behavior when .babelrc is present)

    function *simplestIterator() {
        yield 42;
    }

    for (let v of simplestIterator()) {
        console.log(v);
    }

}

软件包是:

$ npm ls --depth 0
simple-babel-serverside-node-only-archetype@1.0.0 /home/mperdikeas/regeneratorRuntimeNotDefined
├── babel-cli@6.7.5
├── babel-core@6.7.6
├── babel-polyfill@6.7.4
├── babel-preset-es2016@6.0.11
└── babel-runtime@6.6.1

.babelrc 的内容如下:

$ cat .babelrc 
{
    "presets": ["es2016"]
}

然而,当作用域被移除并且simplestIterator被放置在全局作用域时,它会失败,显示如下错误:

ReferenceError: regeneratorRuntime is not defined

更加奇怪的是,如果移除或重命名.babelrc文件,则无论是否存在作用域,代码都会成功执行。顺便说一下,无论是作用域还是IIFE封装生成器都没有区别。

演示此行为的最小GitHub仓库在这里

观察此行为:

git clone https://github.com/mperdikeas/regeneratorRuntimeNotDefined.git
cd regeneratorRuntimeNotDefined/
npm install
npm run build && npm run start

上述代码将在控制台输出42。现在,删除作用域并观察会发生什么。然后将.babelrc重命名,以便再次使用(带或不带作用域都可以)。

我的问题是:

  • 为什么es2016 Babel预设会触发此错误?
  • 为什么将生成器放入作用域中会解决问题?

更新

根据接受的答案,并且由于这是我编写的模块的代码,我最终做了以下操作:

require('babel-polyfill');
module.exports = require('./app.js');
3个回答

48

Babel假设polyfill将在您的应用程序中加载任何其他内容之前加载,但您正在使用函数声明,这意味着它存在并且可以在require被调用之前就能使用了

对于生成器,需要regeneratorRuntime,它由polyfill提供,但是当初始化regenerator时,polyfill尚未加载。

Babel团队的建议是创建两个文件:

index.js

require('babel-polyfill');
require('./app');

是的;仅仅稍微改了一下语法,因为这段代码在一个模块中(请查看我提问末尾的更新)。 - Marcus Junius Brutus
1
如果你正在制作一个发布的模块,你根本不应该使用babel-polyfill,它是为顶级应用程序设计的。你的库应该假设它是由应用程序加载的,或者使用babel-plugin-transform-runtime来注入ES6库功能的显式导入。库不应该通过加载polyfills来改变全局状态。 - loganfsmyth

10

你可以使用 es2015 预设和 transform-regenerator 插件完成以下操作:

.babelrc

{
  "presets": ["es2015"],
  'plugins': [
    'transform-regenerator'
  ]
}

代码

let regeneratorRuntime =  require("regenerator-runtime");
// You code with ES6 generators

顺便提一下,当然你应该安装babel-plugin-transform-regenerator的npm包。


6
为什么巴别塔不自己完成翻译呢?为什么我要去做巴别塔的工作? - Finesse
@Finesse 因为只有您知道将 regenerator runtime 包含到您的程序中的最佳方法。例如使用 require 函数调用或 ES6 import 语句。或者其他一些模块实现技术。 - Mark Lavrynenko
2
一个更通用的解决方案是 babel-plugin-transform-runtime,它包括了 regenerator,还有 polyfill 和 helpers,可以通过配置打开或关闭其中任何一个。在我的情况下(babel 6+),不需要显式地使用 require。https://www.npmjs.com/package/babel-plugin-transform-runtime - Raman
1
@Finesse的评论让我笑了:D :D - Praneet Nadkar

3

我知道这个问题已经有答案了,但是很遗憾,他们的方法并没有解决我的问题。 解决方法是在文件中导入babel babel-polyfills

import "core-js/stable";
import "regenerator-runtime/runtime";

您可以在Babel官方文档该文章中找到相关内容。

注:该内容涉及IT技术,建议您在阅读时结合专业知识。

1
我不需要导入 "core-js/stable"; - andyw

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