web-dev-qa-db-fra.com

Nom d'importation de la variable ES6 dans node.js?

est-il possible d'importer quelque chose dans le module en fournissant un nom de variable lors de l'importation ES6?

C'est à dire. Je veux importer un module à un moment d'exécution en fonction des valeurs fournies dans une configuration:

import something from './utils/' + variableName;
88
Vytautas Butkus

Pas avec l'instruction import. import et export sont définis de manière à pouvoir être analysés statiquement, de sorte qu'ils ne puissent pas dépendre des informations d'exécution.

Vous recherchez l'API loader (polyfill) , mais je ne comprends pas très bien le statut de la spécification:

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

En plus de La réponse de Felix , je ferai remarquer explicitement que ceci n'est actuellement pas autorisé par la grammaire ECMAScript 6 :

Déclaration d'importation:

  • import _ ​​ImportClause FromClause;

  • import _ ​​ModuleSpecifier;

FromClause:

  • de _ ​​ModuleSpecifier

ModuleSpecifier:

  • StringLiteral

Un ModuleSpecifier ne peut être qu'un StringLiteral, pas tout autre type d'expression comme un AdditiveExpression.

25
apsillers

Bien que ce ne soit pas réellement une importation dynamique (par exemple, dans mon cas, tous les fichiers que je suis en train d'importer ci-dessous seront importés et regroupés par webpack, ils ne sont pas sélectionnés au moment de l'exécution), un motif que j'ai utilisé peut aider dans certaines circonstances: :

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

const templates = {
  Template1,
  Template2
};

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

ou bien:

// 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;

Je ne pense pas que je peux me remettre aussi facilement par défaut avec require(), ce qui jettera une erreur si j'essaie d'importer un chemin de modèle construit qui n'existe pas.

Vous trouverez de bons exemples et des comparaisons entre require et import peuvent être trouvés ici: http://www.2ality.com/2014/09/es6-modules-final.html

Excellente documentation sur la réexportation de @iainastacio: http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles

Je suis intéressé d'entendre des commentaires sur cette approche :)

22
ptim

Il existe une nouvelle spécification appelée dynamic import pour les modules ES . En gros, vous appelez simplement import('./path/file.js') et vous êtes prêt à partir. La fonction renvoie une promesse, résolue avec le module si l'importation a réussi.

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

Cas d'utilisation

Les cas d'utilisation incluent l'importation de composants basés sur route pour React, Vue, etc., ainsi que la possibilité de charger paresseux des modules, une fois qu'ils sont requis pendant l'exécution.

Informations complémentaires

Voici une explication sur Google Developers .

Compatibilité du navigateur

Selon MDN , il est supporté par tous les navigateurs Chrome actuels et dans Firefox 66 derrière un drapeau.

7
Nicolai Schmid

vous pouvez utiliser la notation non ES6 pour le faire. C'est ce qui a fonctionné pour moi:

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

J'aime moins cette syntaxe, mais ça marche:
au lieu d'écrire 

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

utilisez cette syntaxe:

let memberName = require("path" + "fileName");
3
Gil Epshtain

Je le ferais comme ça

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
0
april

L'importation dynamique () (disponible dans Chrome 63+) fera votre travail. Voici comment:

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

Je comprends la question spécifiquement posée pour ES6 import dans Node.js, mais ce qui suit pourrait aider les autres à la recherche d’une solution plus générique:

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

Si vous importez un module ES6 et que vous devez accéder à l'exportation default, vous devrez utiliser l'un des éléments suivants:

let variableName = "es6.js";

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

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

Vous pouvez également utiliser la déstructuration avec cette approche, ce qui peut ajouter une connaissance accrue de la syntaxe à vos autres importations:

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

Malheureusement, si vous souhaitez accéder à default ainsi qu'à la déstructuration, vous devrez effectuer cette opération en plusieurs étapes:

// 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;
0
MCTaylor17