ReferenceError: restoreatorRuntime не определен (но работает внутри области)

Я столкнулся с этим странным явлением:

ReferenceError: regeneratorRuntime is not defined

... который мне удалось воспроизвести в очень минимальной настройке (по сравнению с аналогичными вопросами 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
[email protected] /home/mperdikeas/regeneratorRuntimeNotDefined
├── [email protected]
├── [email protected]
├── [email protected]
├── [email protected]
└── [email protected]

Содержимое .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');

Ответ 1

Babel предполагает, что polyfill будет загружен перед чем-либо еще в вашем приложении, но вы используете объявление функции, которое было поднято, что означает, что оно существует и может использоваться до того, как был вызван require.

В случае генераторов нам понадобится regeneratorRuntime, который предоставляется polyfill, но polyfill не загружается, когда регенератор инициализирован.

Рекомендация команды Babel состоит в том, чтобы сделать два файла:

index.js

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

Ответ 2

Кроме того, вы можете сделать следующее: с предустановленным и преобразованным регенератором-плагином es2015:

.babelrc

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

Код

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

P.S. Конечно, вы должны установить пакет babel-plugin-transform-replator npm.