Динамический System.import с веб-пакетом?

Я пытаюсь перенести написанный мной код ES6, который использует systemjs + Babel.

У меня не было проблем с портированием большей части кода.

Однако у меня есть код, который должен динамически загружать модуль ES6, например:

function load(src) {
    System.import(src).then(function() {});
}

src — это внешний модуль ES6, который также может иметь зависимости (статический импорт).

Как я могу перенести этот код в Webpack? Если я попытаюсь использовать оператор require, я получу ПРЕДУПРЕЖДЕНИЕ, что кажется нормальным в соответствии с документацией Webpack.


person warpdesign    schedule 19.03.2016    source источник


Ответы (4)


Предыдущие ответы были правильными, но теперь в webpack 2.2 + babel (на момент написания v2.2.0-rc.3 — последняя версия), мы можем это сделать. Я не проверял себя, но только что провел исследование, которое привело меня сюда.

Прочтите это в документации по веб-пакету: Разделение кода с помощью es2015

Чуть ниже этого раздела находятся Динамические выражения с этим примером:

function route(path, query) {
  return import("./routes/" + path + "/route")
    .then(route => new route.Route(query));
}
// This creates a separate chunk for each possible route

Обязательно обратите внимание, что вам потребуется установить плагин Syntax Dynamic Import, как упоминает документ.

person sic1    schedule 06.01.2017
comment
import предпочтительнее System.import()? - person notgiorgi; 22.01.2017
comment
@notgiorgi Это зависит от вашего варианта использования IMO. Если вам нужно импортировать только один файл, и он не обязательно должен быть динамическим, то, просто выполнив System.import webpack, вы создадите только один дополнительный пакет, что сократит время сборки. Если вы сделаете динамическое import, webpack создаст пакет для каждого потенциального пути, который он может найти в вашей ситуации, что потенциально может увеличить время сборки. - person sic1; 25.01.2017
comment
Я не вижу задокументированного поведения. function getStatic() { return import("./component) } function getDynamic(path) { return import("./" + path) } getStatic() // works fine getDynamic('component') // throws error: Cannot find module - person Joseph Fraley; 15.02.2017

Webpack 1 не поддерживает System.import, вы можете обойти это, используя require.ensure Webpack для динамической загрузки модулей. Подробности этого подхода можно найти здесь: https://webpack.github.io/docs/code-splitting.html#es6-modules

В зависимости от того, что именно вы хотите сделать, вам также может понадобиться использовать функцию Webpack context, см. здесь дополнительную информацию https://webpack.github.io/docs/context.html

Webpack 2 должен решить эти проблемы, поскольку он будет напрямую поддерживать ES6 и System.import.

person David Burrows    schedule 15.06.2016

У вас нет такой вещи, как «динамическая загрузка» в веб-пакете (поскольку упаковщик должен перейти ко всем вашим зависимостям модуля). Самое близкое к тому, чего вы хотите достичь (и правильный способ сделать это в веб-пакете), - это использовать require.ensure - см. документацию.

Один из способов превратить ваш код SystemJS в веб-пакет:

function load(moduleName) {
    switch (moduleName) {
        case 'foo':
            require.ensure([], require) => {
                const foo = require('./foo.js');
                // do something with it
            }
            break;
        case 'bar':
            require.ensure([], require) => {
                const bar = require('./bar.js');
                // do something with it
            }
            break;
    }
}

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

Вы можете посмотреть пример здесь

person topheman    schedule 19.03.2016
comment
К сожалению, я не могу использовать переключатель/регистр: я понятия не имею, как называется файл. - person warpdesign; 19.03.2016
comment
Почему вы не знаете имя файла? Это не имеет смысла в WebPack. В WebPack вы связываете свои файлы, поэтому все ваши файлы должны находиться в вашей файловой системе. Итак, вам нужно знать свои файлы заранее, чтобы они были в вашем исходном коде, верно? - person egucciar; 21.05.2016
comment
У вас нет такой вещи, как динамическая загрузка в веб-пакете (поскольку упаковщик должен перейти ко всем зависимостям вашего модуля). Это просто неправильно. require.ensure выполняет настоящую динамическую загрузку. Проверьте вкладку сети в консоли разработчика: выполняются фактические запросы на фактические дополнительные файлы пакетов. Весь смысл этой конструкции: позволить Webpack выполнять разбиение кода. - person Stijn de Witt; 27.01.2017
comment
Я бы посоветовал вам сделать функцию загрузки, инкапсулирующую каждый require.ensure (вы можете управлять обратными вызовами по-другому). На самом деле это плохой совет. Хотя код и так громоздкий, попытка его инкапсулировать только усугубит ситуацию, поскольку Webpack нужны буквальные имена модулей, чтобы он мог выполнять условную загрузку. Не делай require.ensure([myVariable], ..., а делай require.ensure(['./my/module'], ... - person Stijn de Witt; 27.01.2017

Вы можете попробовать использовать такую ​​библиотеку, как little-loader, чтобы справиться с этим. Пример:

var load = require('little-loader');

load('<src>', function(err) {
    // loaded now, do something
});
person Juho Vepsäläinen    schedule 20.03.2016
comment
Я думаю, что мне действительно придется использовать какой-то внешний загрузчик. Но мне нужен результат выполнения скрипта: я не уверен, что little-loader это поддерживает. - person warpdesign; 21.03.2016
comment
Об этом можно было спросить на проекте. В некоторых случаях интересной альтернативой может быть загрузка кода через ajax и eval его в песочнице на основе iframe. Затем зафиксируйте результат оттуда. Однако это может быть излишним для ваших целей. - person Juho Vepsäläinen; 21.03.2016
comment
Учитывая, что ваш src может иметь собственные зависимости (статический импорт), это может быть не совсем тривиальной проблемой для решения. Вам нужно будет загрузить эти импорты, прежде чем даже пытаться оценить модуль, который вы хотите загрузить. - person Juho Vepsäläinen; 21.03.2016