Миграция с Webpack 1.x на 2.x

В Webpack 1.x я регулярно делал следующее:

require.ensure([ './mod2.js' ], ( require ) => {
    setTimeout(() => {
        // some later point in time, most likely through any kind of event
        var data = require( './mod2.js' ); // actual evaluating the code
    },1100);
}, 'myModule2');

С помощью этой методики мы смогли перенести пакет webpack поверх проводника, но затем оцениваем фактическое содержимое (код JavaScript) из этого пакета в некоторый более поздний момент времени. Кроме того, используя require.ensure, мы могли бы назвать пакет, в данном случае myModule2, чтобы мы могли видеть имя/псевдоним, когда в комплекте выполнялось выполнение webpack.

В Webpack 2.x новый способ использования - System.import. Пока мне нравится получать объект Promise, у меня есть два вопроса с этим стилем. Эквивалент вышеуказанного кода будет выглядеть следующим образом:

System.import( './mod2.js' ).then( MOD2 => {
    // bundle was transferred AND evaluated at this point   
});
  • Как мы можем разделить передачу и оценку сейчас?
  • Как мы все еще можем назвать пакет?

Документация Webpack в Github говорит следующее:

Полная динамическая динамика требует по умолчанию

Зависимость с только выражением (например, require (expr)) теперь создать пустой контекст вместо контекста полного каталог.

Лучший рефакторинг этого кода, так как он не будет работать с модулями ES6. Если это невозможно использовать ContextReplacementPlugin, чтобы намекнуть компилятор к правильному разрешению.

Я не уверен, сыграет ли это роль в этом случае. Они также говорят о разделении кода там, но это довольно кратко, и они не упоминают ни о каких "проблемах" и как обходиться.

Ответы

Ответ 1

tl; dr: System.resolve и System.register делают большую часть того, что вы хотите. Остальная часть этого ответа заключается в том, почему require.ensure не может и как System.import вызывает остальные.

Я думаю, что модули ES6 не позволяют этому работать хорошо, хотя после него с помощью спецификаций релевантов сложно, поэтому я могу быть абсолютно неправым.

Тем не менее, давайте начнем с нескольких ссылок:

Первая ссылка объясняет больше поведения, хотя я не совсем уверен, как это нормализуется. Последнее объясняет детали реализации на стороне JS. Поскольку никакие платформы не реализуют это, у меня нет ссылок на то, как он действительно работает в реальной жизни, и нам придется полагаться на спецификацию.

require, который был доступен в webpack 1.x - это mashup для CommonJS и AMD. Сторона CommonJS описана в ссылке # 3, в частности в разделе "Контекст модуля". Нигде не упоминается require.ensure, а также спецификация AMD (такая как она есть), поэтому это просто изобретение webpack. То есть, эта функция никогда не была реальной, в смысле того, чтобы быть где-то официальным и причудливым.

Тем не менее, я думаю, что require.ensure конфликтует с модулями ES6. Вызов System.import должен вызывать метод import из Loader объект. В соответствующем разделе в ссылке # 2 это явно не указано, но §10.1 упоминает о подключении загрузчика к System.

Loader.prototype.import метод не очень привлекателен, а шаг 4 - единственный, который нас интересует:

  1. Возвращает результат преобразования Resolve (loader, name, referrer) с обработчиком выполнения, который при вызове с ключом аргумента выполняет следующие шаги:
    • Пусть запись будет выполнена с подтверждением (загрузчик, ключ).
    • Возвращает результат преобразования LoadModule (запись, "экземпляр" ) с обработчиком выполнения, который при вызове выполняет следующие шаги:
      • Return EnsureEvaluated (запись).

Поток определяется разрешением-регистром-нагрузкой, и вы хотите разбить нагрузку и оценить. Обратите внимание, однако, что этап загрузки вызывает LoadModule с stage, установленным на "instantiate". Это подразумевает и, вероятно, требует, чтобы модуль уже был переведен через RequestTranslate, который делает большую часть сильного разбора, когда он пытается найти модуль точка входа и т.д.

Это уже сделало больше работы, чем вы хотите, из ее звуков. Поскольку для основ загрузки модуля требуется известная точка входа, я не думаю, что существует способ избежать синтаксического анализа и частичной оценки модуля с помощью вызовов, открытых из System. Вы уже это знали.

Проблема в том, что System.import не может знать - до тех пор, пока не будет проведен синтаксический анализ - должен ли модуль быть модулем ES6, который должен быть оценен, или пакет веб-пакетов, который можно отложить. Разбор должен быть выполнен, чтобы выяснить, нужно ли нам разбираться, что приводит к проблеме курица и яйца.

До этого момента мы проходили путь от System.import через Loader. Вызов import диктует, на какой стадии импорта мы находимся, предполагая, что вы хотите пройти полный сквозной процесс загрузки. Основные вызовы, такие как Loader.prototype.load, обеспечивают мелкозернистый контроль над этими этапами.

Я не уверен, как вы будете вызывать первые два этапа (выборка и перевод), но если вы смогли перевести и зарегистрировать модуль, последующие вызовы должны просто оценить и вернуть его.

Если спецификация является точной, это должно быть показано (в поддерживающих реализациях) с помощью свойства System.loader и будет иметь методы, необходимые для вызова. Есть большие части потока, к которому у вас нет доступа, поэтому я предлагаю не делать этого и вместо этого настраивать свой код, так что ничего значительного не запускается при загрузке модуля. Если это невозможно, вам нужно воссоздать поток вверх, зарегистрировавшись, но не стесняйтесь оценки.