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

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

Приведенный выше код не компилируется; он выдает SyntaxError: ... 'import' и 'export' могут появляться только на верхнем уровне.

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

ericsoco

Ответы (14)

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

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

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

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

Импорт и Экспорт условно в JS

const value = (
    await import(`${condtion ? `./file1.js` : `./file2.js`}`)
).default

export default value

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

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

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

Чтобы узнать больше о динамическом импорте, перейдите по ссылке ниже

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#dynamic_imports

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]);

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

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

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

Нет, нельзя!

Однако, столкнувшись с этой проблемой, вы должны переосмыслить то, как вы организуете свой код.

До модулей ES6 у нас были модули CommonJS, в которых использовался синтаксис require (). Эти модули были «динамическими», что означало, что мы могли импортировать новые модули в зависимости от условий в нашем коде. - источник: https://bitsofco.de/what-is-tree-shaking/

Думаю, одна из причин, по которой они отказались от поддержки ES6, заключается в том, что его компиляция будет очень сложной или невозможной.

Look at this example for clear understanding of how dynamic import works.

Пример импорта динамического модуля

Базовые знания об импорте и экспорте модулей.

Модули JavaScript Github

Модули Javascript MDN

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

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

Похоже, ответ таков, что на данный момент вы не можете.

http://exploringjs.com/es6/ch_modules.html#sec_module-загрузчик-api

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

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

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

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 она требует инициализации.

Важное отличие, если вы используете режим динамического импорта Webpack eager:

if (normalCondition) {
  // это будет включено в комплект, независимо от того, используете вы его или нет
  Импортировать(...);
}

if (process.env.SOMETHING === 'true') {
  // это не будет включено в комплект, если ЧТО-ТО не соответствует истине
  Импортировать(...);
}

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

let something = null;
let other = null;

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

Обновление 2020

Теперь вы можете вызвать ключевое слово import как функцию (например, import ()) для загрузки модуля во время выполнения.

Пример:

const mymodule = ожидание импорта (имя модуля);

или:

импорт (имя модуля)
    .then (mymodule => / * ... * /);

См. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#Dynamic_Imports

2022 WebDevInsider