В начале прошлого года было предложено ввести в JavaScript возможность динамического импорта. Если кто не знает, то сейчас в JavaScript нативно поддерживается только статическая импортизация и для этого есть причины, но это тема отдельного разговора. Предложение было реализовано и включено в список ближайшего обновления ECMAScript. Google Chrome с 63 версии уже поддерживает эту возможность. Я немного расскажу что это такое и где это может пригодиться.


Динамический импорт (dynamic import) используется почти также как и статический, но имеет несколько ключевых отличий:


Синтаксически динамический импорт подобен вызову функции: import(‘path/to/module.js’);


Команда import(‘path/to/file.js’) возвращает Promise, который перейдет в состояние fulfilled после того, как будет подтянут и установлен сам модуль непосредственно, так и все его зависимости. А это значит, что мы можем написать вот так:


import('path/to/module.js')
  .then(module => {
    module.loadPageInto(main);
  })
  .catch(err => {
    main.textContent = err.message;
  });

Или даже так:


const module = await import('path/to/module.js');

Важное замечание: хотя динамический импорт синтаксически и выглядит как вызов функции import(), но функцией не является. Он не наследуется от Function.prototype, а это значит что его нельзя вызвать через call или apply.


Применений динамическому импорту можно найти много, require.js уже давно имеет подобную возможность и webpack, если не ошибаюсь тоже, поэтому многие из вас, наверное, уже давно используют подобный функционал. Теперь это делать можно будет нативно. Но с другой стороны, возможность импортировать динамически, в зависимости от условий, во время рантайма дает и место для более запутанного кода, хотя понимаю что налепить плохой код можно с чем угодно, не в инструменте дело. Пишите ваше мнение в комментарии, что вы думаете о dynamic import.


Более детально можно почитать и посмотреть тут:
https://github.com/tc39/proposal-dynamic-import
https://developers.google.com/web/updates/2017/11/dynamic-import
https://www.youtube.com/watch?v=eg8eLH52d4s&t=31s

Комментарии (14)


  1. apapacy
    07.06.2019 09:25

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


    1. worldxaker
      07.06.2019 10:43

      ага, от того ещё более странно что в одной из последних версий вебпака его сломали и до сих пор не починили


      1. apapacy
        07.06.2019 14:36

        У мен я сейчас такой по версиям в одном из проектов стек (начал н этой недели с нуля) чанки работют как положено. Но правда я с плагинами это делаю.

        "@babel/core": "^7.4.5",
        "@babel/plugin-proposal-class-properties": "^7.4.4",
        "@babel/plugin-proposal-decorators": "^7.4.4",
        "@babel/plugin-transform-modules-commonjs": "^7.4.4",
        "@babel/plugin-transform-runtime": "^7.4.4",
        "@babel/preset-env": "^7.4.5",
        "@babel/preset-react": "^7.0.0",
        "@riotjs/compiler": "^4.2.4",
        "@riotjs/hot-reload": "^4.0.0",
        "@riotjs/webpack-loader": "^4.0.0",
        «babel-plugin-dynamic-import-node»: "^2.2.0",
        «babel-plugin-syntax-dynamic-import»: "^6.18.0",
        «babel-plugin-transform-decorators-legacy»: "^1.3.5",
        «fast-async»: "^6.3.8",
        «react-hot-loader»: "^4.9.0",
        «webpack»: "^4.32.2",
        «webpack-cli»: "^3.3.2",
        «webpack-dev-middleware»: "^3.7.0",
        «webpack-hot-middleware»: "^2.25.0"


        1. worldxaker
          09.06.2019 18:14

          не туда


      1. Odrin
        07.06.2019 15:44
        +3

        А что конкретно сломали, можно ссылку на issue?


        1. worldxaker
          09.06.2019 18:27
          +1

          1. Odrin
            10.06.2019 10:14
            +1

            Ну и как бы ошибка в npm, а не webpack.


  1. helgihabr
    07.06.2019 10:50

    Пока в FF javascript.options.dynamicImport не будет включен по-умолчанию, нативно использовать динамический импорт рановато.
    Кстати, подскажите, как дела обстоят с этим в IE или Edge? Или что там в Windows используется.


    1. ihost
      07.06.2019 10:59
      +1

      В Edge и Safari эта фича уже давно поддерживается и работает — больше двух лет как — см. https://habr.com/ru/company/tuturu/blog/326716/ — как собственно и с множеством современных ES-фичей, которые в Edge поступают раньше, чем в хром


    1. MikeLP
      07.06.2019 13:22

      Начиная с 67 версии FF поддерживает динамический импорт по умолчанию.


      1. helgihabr
        07.06.2019 13:28

        Хм, действительно, так. Спасибо.

        FF 67+
        From version 66 until version 67 (exclusive): this feature is behind the javascript.options.dynamicImport preference (needs to be set to true). To change preferences in Firefox, visit about:config.


    1. apapacy
      07.06.2019 14:40

      Не уверен что использовать нативно вообще перспективная идея. Это немного напоминает requirejs Сначала все ображдовались что можно импортировать зависимости а не прописывать все в тэгах script. Потом оказалось что загрузка сотен мелких модулей это очень долго и стали все rj-иксить в один огромный файл. Потом и это оказалось ужасно т.к. долго. И тут пришли чанки которые регулируются как раз динамическим импортом.


  1. ihost
    07.06.2019 11:03
    +1

    Google Chrome с 63 версии уже поддерживает эту возможность

    А Edge и Safari поддерживают эту фичу уже два года — https://habr.com/ru/company/tuturu/blog/326716/. Оперативно, может еще через десяток лет хром наконец-то оптимизирует потребление памяти до уровня Edge


    1. justboris
      07.06.2019 20:49
      +2

      Скорее наоборот, ведь Edge же переходит на Chromium