4 Мар


2019

Динамический импорт объектов в js, на примере Vue.js.

Очень часто приходится работать с большим количеством данных, экспортировать каждый раз которые является достаточно рутинной задачей. Реализация динамического иморта неплохо продемонстрирована в nuxt.js. В данном фреймворке это выглядит достаточно лаконично и естественно. Вебпак позволяет динамически подгружать модули, и обращаться к ним через враппер. Данный метод, в основном, я использую для динамической подгрузки модулей Vuex. Однако его можно неплохо преспособить и для других задач. Вплоть до импорта каких-либо внешних json структур в проект с удаленного сервера.

Собственно что имеем

function generateStoreName(fileName) {
  return fileName.slice(2, fileName.length - 3);
}

function collectStore() {
  const requireModule = require.context('.', false, /\.js$/);
  const stores = {};
  requireModule.keys().forEach((fileName) => {
    if (fileName === './index.js') return;
    const storeName = generateStoreName(fileName);
    stores[storeName] = requireModule(fileName).default;
  });
  return stores;
}

const collectedStores = collectStore();

С помощью require.context собираем файлы из текущей директории (игнорируем сабфолдер, учитывая то что модули находятся в js файлах, в случае если они распределены по подпапкам скрипт придется немного переписать).

Далее собираем название файлов в объект stores, на этом этапе имена файлов можно привести к cebab-case. Функции generateStoreName формирует текущий ключ для доступа к объекту. 

В процессе написания кода столкнулся с проблемой импорта ленивых компонентов, к сожалению решить ее приведенным выше путем мне не удалось.

В приведенном ниже примере я экспортировал модуль целиком

function collectItems() {
  const items = {};
  const requireModule = require.context('./Items/', false, /^.*\.js$/, 'lazy');
  requireModule.keys().filter((fileName) => {
    const slicedFilename = fileName.slice(2, fileName.length - 3);
    items[slicedFilename] = require(`./Items/${slicedFilename}`);
  });
  return themes;
}

const items = collectThemes();

export default items;

Далее при импорте можно обратиться к default, либо к экспортируемой константе.

Я до конца не уверен причину возникновения ошибки рекурсивной зависимости, гугление по англоязычным форумам тоже дало такой себе результат (нашел совет с использованием System.import, а также рабочую версию для импорта Vue компонентов). Изначальный замысел, как и в случае с vuex, был в том чтобы иметь доступ при импорте к уже инициализированным объектам. 

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

Также в будущем скорее всего опишу процесс динамического импорта vue компонентов (как-то столкнулся с такой задачей). Данные компоненты использовали 1 общий миксин с враппером вокруг настроек импортируемых компонентов (звучит сложно и непонятно, однако на деле все достаточно просто).

фичи
web
best practices
vue.js
webpack