web-dev-qa-db-fra.com

Comment puis-je importer conditionnellement un module ES6?

J'ai besoin de faire quelque chose comme:

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

Le code ci-dessus ne compile pas; il jette SyntaxError: ... 'import' and 'export' may only appear at the top level.

J'ai essayé d'utiliser System.import comme indiqué ici , mais je ne sais pas d'où vient System. Est-ce une proposition ES6 qui n'a pas été acceptée? Le lien vers "API de programmation" de cet article me renvoie à une page de documentation deprecated .

129
ericsoco

Nous avons maintenant une proposition d'importation dynamique avec l'ECMA. Ceci est à l'étape 3. Ceci est également disponible en tant que babel-preset .

Voici une façon de faire un rendu conditionnel selon votre cas.

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

Cela renvoie essentiellement une promesse. La résolution de la promesse devrait avoir le module. La proposition comporte également d'autres fonctionnalités telles que plusieurs importations dynamiques, importations par défaut, import de fichier js, etc. Vous trouverez plus d'informations sur les importations dynamiques ici

80
thecodejack

Si vous le souhaitez, vous pouvez utiliser require. C'est un moyen d'avoir une instruction d'exigence conditionnelle.

let something = null;
let other = null;

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

Vous ne pouvez pas importer sous condition, mais vous pouvez faire le contraire: exporter quelque chose sous condition. Cela dépend de votre cas d'utilisation, ce travail peut donc ne pas vous convenir.

Tu peux faire:

api.js

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

const exportedAPI = shouldUseMock ? mockAPI : realAPI
export default exportedAPI

apiConsumer.js

import API from './api'
...

J'utilise cela pour me moquer de bibliothèques d'analyse telles que mixpanel, etc ... car je ne peux pas avoir plusieurs versions ou notre interface actuellement. Pas le plus élégant, mais fonctionne. J'ai juste quelques "si" ici et là en fonction de l'environnement car dans le cas de mixpanel, il doit être initialisé.

35
Kev

On dirait que la réponse est que, à partir de maintenant, vous ne pouvez pas.

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

Je pense que l’intention est de permettre une analyse statique autant que possible, et les modules importés sous condition ne le permettent pas. Il faut également mentionner - j'utilise Babel , et je suppose que Babylle ne prend pas en charge System car l’API du chargeur de modules n’est pas devenue un standard ES6.

9
ericsoco

Regardez cet exemple pour bien comprendre le fonctionnement de l'importation dynamique.

Exemple d'importations de module dynamique

Pour comprendre les notions d'importation et d'exportation de modules.

modules JavaScript Github

Modules Javascript MDN

0
Ashok R

Les importations conditionnelles peuvent également être réalisées avec un ternaire et require()s:

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

Cet exemple provient des documents globaux de ES Lint: https://eslint.org/docs/rules/global-require

0
Elliot Ledger

J'ai pu réaliser cela en utilisant une fonction immédiatement appelée et une instruction require.

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

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

l'obscurcir dans un eval a fonctionné pour moi, en le cachant de l'analyseur statique ...

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

require() permet d'importer un module au moment de l'exécution et permet également une analyse statique telle que import si elle est utilisée avec des chemins d'accès littéraux de chaîne. L'afficheur a besoin de cela pour choisir des dépendances pour cet ensemble.

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

Pour une résolution de module dynamique avec prise en charge complète de l'analyse statique, indexez d'abord les modules dans un indexeur (index.js) et importez-les dans le module hôte.

// 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]);
0
Shoaib Nawaz