Динамически загружать модуль, который не находится в теге скрипта с type = "module"? - PullRequest
0 голосов
/ 06 ноября 2018

Можно ли использовать импорт без тега сценария, уже установленного для указанного модуля?

Моя проблема в том, что я хочу загружать модули динамически на основе файла конфигурации, например:

Структура папок:

|-- main.js
|-- config.json.js
|-- modules
    |-- module1.js
    |-- module2.js
    |-- module3.js

Index.html head:

<script src="/config.json.js" type="module"></script>
<script src="/main.js"></script>

config.json.js:

export default {

  modules : ['module1', 'module3']

}

main.js:

import config from '/config.json.js'

//Loading modules defined in config
config.modules.forEach(moduleName => {
  import(`modules/${moduleName}`)
  .then( module => {
    console.log(`${module.name} loaded.`);
  )}
})

Выше не будет работать, так как модули не были определены в теге скрипта.

Можно ли как-нибудь добиться этого, используя vanilla JS и поддерживая его в чистоте?

Ответы [ 2 ]

0 голосов
/ 28 июля 2019

Редактировать! Динамический импорт загружен в Firefox 67 + .

  (async () => {
    await import('./synth/BubbleSynth.js')
  })()

https://caniuse.com/#feat=es6-module-dynamic-import


Старый ответ:

Чтобы импортировать другие модули после загрузки DOM , можно создать не совсем чистый, но работающий способ создания нового скрипта вызывающего типа модуля.

/* Example */
/* Loading BubbleSynth.js from «synth» folder*/
let dynamicModules = document.createElement("script")
dynamicModules.type = "module"
dynamicModules.innerText = "import * as bsynth from '../synth/BubbleSynth.js'"
/* One module script already exist. eq: «main.js», append after it */ 
document.querySelector("script[type='module']").parentElement.appendChild(dynamicModules)

Уничтожение скрипта вызывающего модуля не вредит прошлым вызовам:

document.querySelectorAll("script[type='module']")[1].outerHTML = ""
// *BubbleSynth* is still in memory and is running

Но добавление нового вызова модуля в этот скрипт не работает. Должен быть создан новый скрипт модуля вызывающего абонента.

Как функция:

function dynModule(me){
  let dyn = document.createElement("script")
  dyn.type = "module"
  dyn.innerText = `import * as ${me} from '../synth/${me}.js'`
  document.querySelector("script[type='module']").parentElement.appendChild(dyn)
  document.querySelectorAll("script[type='module']")[1].outerHTML = ""
}

dynModule("BubbleSynth")
0 голосов
/ 06 ноября 2018

Да, вы можете, если ваш скрипт загрузчика помечен как module

<script type="module">
  const moduleSpecifier = './myModule.mjs';
  import(moduleSpecifier)
    .then((module) => {
      // do something
    });
</script>

Хотя, в вашем случае, простого forEach может быть недостаточно. Вам может понадобиться Promise.all или аналогичный, если вы хотите подождать всех модулей для загрузки из вашей конфигурации.

const modules = config.modules.map(moduleName => import(`modules/${moduleName}`))

Promise.all(modules)
  .then(modules => {
    // modules is an array of all your loaded modules
    console.log('All modules loaded.');
  )}

Дальнейшее чтение:

...