Имя импорта переменной ES6 в node.js?

Можно ли импортировать что-то в модуль, предоставляя имя переменной при использовании импорта ES6?

т.е. Я хочу импортировать некоторый модуль во время выполнения в зависимости от значений, представленных в config:

import something from './utils/' + variableName;

Ответ 1

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

Вы ищите API-интерфейс загрузчика (polyfill), но я немного неясен о состоянии спецификации:

System.import('./utils/' + variableName).then(function(m) {
  console.log(m);
});

Ответ 2

В дополнение к ответу Феликса, я четко укажу, что в настоящее время это не разрешено грамматикой ECMAScript 6:

ImportDeclaration :

  • import ImportClause FromClause;

  • import ModuleSpecifier;

FromClause :

  • из ModuleSpecifier

ModuleSpecifier :

  • СтроковойЛитерал

Модуль ModuleSpecifier может быть только StringLiteral, а не любым другим выражением типа AdditiveExpression.

Ответ 3

Хотя на самом деле это не динамический импорт (например, в моих обстоятельствах все импортируемые мной файлы будут импортированы и упакованы с помощью webpack, не выбранных во время выполнения), шаблон, который я использовал, который может помочь в некоторые обстоятельства:

import Template1 from './Template1.js';
import Template2 from './Template2.js';

const templates = {
  Template1,
  Template2
};

export function getTemplate (name) {
  return templates[name];
}

или, альтернативно:

// index.js
export { default as Template1 } from './Template1';
export { default as Template2 } from './Template2';


// OtherComponent.js
import * as templates from './index.js'
...
// handy to be able to fall back to a default!
return templates[name] || templates.Template1;

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

Хорошие примеры и сравнения между требованием и импортом можно найти здесь: http://www.2ality.com/2014/09/es6-modules-final.html

Отличная документация по реэкспорту из @iainastacio: http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

Мне интересно услышать отзывы об этом подходе:)

Ответ 4

Существует новая спецификация, которая называется динамическим импортом для модулей ES. По сути, вы просто вызываете import('./path/file.js') и все import('./path/file.js'). Функция возвращает обещание, которое разрешается с модулем, если импорт был успешным.

async function import() {
   try {
      const module = await import('./path/module.js');
   } catch (error) {
      console.error('import failed');
   }
}

Случаи применения

Варианты использования включают импорт компонентов на основе маршрута для React, Vue и т.д., А также возможность отложенной загрузки модулей, если они необходимы во время выполнения.

Дальнейшая информация

Вот объяснение для разработчиков Google.

Совместимость браузера

Согласно MDN, он поддерживается каждым текущим браузером Chrome и в Firefox 66 за флагом.

Ответ 5

для этого вы можете использовать нотацию без ES6. это то, что сработало для меня:

let myModule = null;
if (needsToLoadModule) {
  myModule = require('my-module').default;
}

Ответ 6

Мне меньше нравится этот синтаксис, но он работает:
вместо написания

import memberName from "path" + "fileName"; 
// this will not work!, since "path" + "fileName" need to be string literal

используйте этот синтаксис:

let memberName = require("path" + "fileName");

Ответ 7

Я бы сделал это так:

function load(filePath) {
     return () => System.import(`${filePath}.js`); 
     // Note: Change .js to your file extension
}

let A = load('./utils/' + variableName)

// Now you can use A in your module

Ответ 8

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

let variableName = "es5.js";
const something = require('./utils/${variableName}');

Обратите внимание: если вы импортируете модуль ES6 и вам нужен доступ к экспорту по default, вам нужно будет воспользоваться одним из следующих:

let variableName = "es6.js";

// Assigning
const defaultMethod = require('./utils/${variableName}').default;

// Accessing
const something = require('./utils/${variableName}');
something.default();

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

// Destructuring 
const { someMethod } = require('./utils/${variableName}');    
someMethod();

К сожалению, если вы хотите получить доступ по default а также к деструктуризации, вам необходимо выполнить это в несколько шагов:

// ES6 Syntax
Import defaultMethod, { someMethod } from "const-path.js";

// Destructuring + default assignment
const something = require('./utils/${variableName}');

const defaultMethod = something.default;    
const { someMethod, someOtherMethod } = something;

Ответ 9

Динамический импорт() (доступен в Chrome 63+) сделает вашу работу. Вот как:

let variableName = 'test.js';
let utilsPath = './utils/' + variableName;
import(utilsPath).then((module) => { module.something(); });

Ответ 10

Использование строк шаблонов ES6 Мне удалось импортировать динамические переменные, вот мой boilerplate - это это универсальный Javascript, но он должен работать с различными конфигурациями:

const myImg = './cute.jpg'
<img src={require(`${myImg}`)} />