Как я могу условно импортировать модуль ES6?

Мне нужно сделать что-то вроде:

if (condition) {
    import something from 'something';
}
// ...
if (something) {
    something.doStuff();
}

Вышеприведенный код не компилируется; он бросает SyntaxError: ... 'import' and 'export' may only appear at the top level.

Я попытался использовать System.import, как показано здесь, но я не знаю, откуда приходит System. Это предложение ES6, которое не было принято? Ссылка на "программный API" из этой статьи вывела меня на страницу устаревшие документы.

Ответ 1

Теперь у нас есть предложение динамического импорта с ECMA. Это в стадии 3. Это также доступно как babel-preset.

Ниже приведен способ выполнения условного рендеринга в соответствии с вашим случаем.

if (condition) {
    import('something')
    .then((something) => {
       console.log(something.something);
    });
}

Это в основном возвращает обещание. Ожидается, что ожидается, что модуль обещания получит модуль. В предложении также есть другие функции, такие как множественный динамический импорт, импорт по умолчанию, импорт файла js и т.д. Здесь вы можете найти дополнительную информацию о динамическом импорте .

Ответ 2

Если вы хотите, вы можете использовать требуют. Это способ получения условного оператора require.

let something = null;
let other = null;

if (condition) {
    something = require('something');
    other = require('something').other;
}
if (something && other) {
    something.doStuff();
    other.doOtherStuff();
}

Ответ 3

Вы не можете импортировать условно, но вы можете сделать обратное: экспортировать что-то условно. Это зависит от вашего варианта использования, поэтому эта работа может быть не для вас.

Вы можете сделать:

api.js

import mockAPI from './mockAPI'
import realAPI from './realAPI'

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

import API from './api'
...

Я использую это, чтобы издеваться над библиотеками аналитики, такими как mixpanel и т.д., потому что в настоящее время я не могу иметь несколько построек или наш интерфейс. Не самый элегантный, но работает. У меня просто есть несколько "если" здесь и там в зависимости от среды, потому что в случае mixpanel ему нужна инициализация.

Ответ 4

Похоже, что ответ заключается в том, что на данный момент вы не можете.

http://exploringjs.com/es6/ch_modules.html#sec_module-loader-api

Я думаю, что цель состоит в том, чтобы максимально использовать статический анализ, и условно импортированные модули нарушают это. Также стоит упомянуть - я использую Babel, и я предполагаю, что System не поддерживается Babel, потому что загрузчик модуля API не стал стандартом ES6.

Ответ 5

у меня получилось скрыть это в eval, скрыв это от статического анализатора...

if (typeof __CLI__ !== 'undefined') {
  eval("require('fs');")
}

Ответ 6

require() - это способ импортировать некоторый модуль во время выполнения, и он одинаково подходит для статического анализа, такого как import если используется со строковыми литеральными путями. Это требуется, чтобы упаковщик выбирал зависимости для комплекта.

const defaultOne = require('path/to/component').default;
const NamedOne = require('path/to/component').theName;

Для динамического разрешения модулей с полной поддержкой статического анализа, сначала индексируйте модули в индексаторе (index.js) и импортируйте индексатор в хост-модуле.

// index.js
export { default as ModuleOne } from 'path/to/module/one';
export { default as ModuleTwo } from 'path/to/module/two';
export { SomeNamedModule } from 'path/to/named/module';

// host.js
import * as indexer from 'index';
const moduleName = 'ModuleOne';
const Module = require(indexer[moduleName]);

Ответ 7

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

const something = (() => (
  condition ? require('something') : null
))();

if(something) {
  something.doStuff();
}

Ответ 8

Условный импорт также может быть достигнут с помощью троичной переменной и require() s:

const logger = DEBUG? require('dev-logger'): require('logger');

Этот пример взят из глобальных документов ES Lint: https://eslint.org/docs/rules/global-require