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

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

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');

person Marcus Junius Brutus    schedule 14.04.2016    source источник


Ответы (3)


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

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

Команда Babel рекомендует создать два файла:

index.js

require('babel-polyfill');
require('./app');
person loganfsmyth    schedule 14.04.2016
comment
да; только немного изменил синтаксис, так как это было внутри модуля (см. обновление в конце моего вопроса). - person Marcus Junius Brutus; 15.04.2016
comment
Если вы делаете опубликованный модуль, вам вообще не следует использовать babel-polyfill, он предназначен для приложений верхнего уровня. Ваша библиотека должна либо предполагать, что она загружена приложением, либо использовать babel-plugin-transform-runtime для внедрения явного импорта для функциональности библиотеки ES6. Библиотеки не должны изменять глобальное состояние, загружая полифиллы. - person loganfsmyth; 15.04.2016

Также вы можете сделать следующее с пресетом es2015 и плагином transform-regenerator:

.babelrc

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

Код

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

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

person Mark Lavrynenko    schedule 14.10.2016
comment
Почему Вавилон не делает этого сам? Я должен делать работу Бабеля? - person Finesse; 19.04.2017
comment
@Finesse, потому что только вы знаете лучший способ включить время выполнения регенератора в свою программу. Например, используя вызов функции require или оператор импорта ES6. Или какой-то другой метод реализации модуля. - person Mark Lavrynenko; 19.04.2017
comment
Более общее решение — babel-plugin-transform-runtime, которое включает в себя регенератор, а также полифилл и хелперы, любой из которых можно включить или выключить через config. В моем случае (babel 6+) явное require не требовалось. npmjs.com/package/babel-plugin-transform-runtime - person Raman; 13.09.2017
comment
Комментарий @Finesse заставил меня смеяться :D :D - person Praneet Nadkar; 06.09.2019

Я знаю, что на это был дан ответ, но, к сожалению, они не решили проблему для меня. что решило, так это импортировать babel babel-polyfills внутри файла

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

вы можете найти его в официальной документации по babeljs или в этой статье

person Mike Araya    schedule 01.03.2020
comment
Мне не нужно было импортировать core-js/stable; - person andyw; 24.03.2020