javascript - nodejs - ¿Nombre de importación variable ES6 en node.js?
nodejs es7 support (9)
Además de la respuesta de Felix , notaré explícitamente que esto no está permitido actualmente por la gramática ECMAScript 6 :
Declaración de importación :
import ImportClause FromClause;
import ModuleSpecifier;
De cláusula :
- de ModuleSpecifier
Módulo Especificador :
- CadenaLiteral
Un ModuleSpecifier solo puede ser un StringLiteral , no cualquier otro tipo de expresión como AdditiveExpression .
¿Es posible importar algo al módulo que proporciona el nombre de la variable mientras se usa la importación ES6?
Es decir, quiero importar algún módulo en tiempo de ejecución dependiendo de los valores proporcionados en una configuración:
import something from ''./utils/'' + variableName;
Entiendo la pregunta específicamente hecha para la
import
ES6 en Node.js, pero lo siguiente podría ayudar a otros que buscan una solución más genérica:
let variableName = "es5.js";
const something = require(`./utils/${variableName}`);
Tenga en cuenta que si está importando un módulo ES6
y necesita acceder a la exportación
default
, deberá usar uno de los siguientes:
let variableName = "es6.js";
// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;
// Accessing
const something = require(`./utils/${variableName}`);
something.default();
También puede usar la desestructuración con este enfoque que puede agregar más familiaridad de sintaxis con sus otras importaciones:
// Destructuring
const { someMethod } = require(`./utils/${variableName}`);
someMethod();
Desafortunadamente, si desea acceder al
default
así como a la desestructuración, deberá realizar esto en varios pasos:
// 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;
Hay una nueva especificación que se llama
importación dinámica
para módulos ES.
Básicamente, simplemente llama a
import(''./path/file.js'')
y listo.
La función devuelve una promesa, que se resuelve con el módulo si la importación se realizó correctamente.
async function import() {
try {
const module = await import(''./path/module.js'');
} catch (error) {
console.error(''import failed'');
}
}
Casos de uso
Los casos de uso incluyen la importación de componentes basados en rutas para React, Vue, etc. y la capacidad de cargar módulos de forma diferida , una vez que se requieren durante el tiempo de ejecución.
Más información
Aquí hay una explicación sobre Google Developers .
Compatibilidad del navegador
Según MDN , es compatible con todos los navegadores de cromo actuales y en Firefox 66 detrás de una bandera.
Lo haría asi
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
Me gusta menos esta sintaxis, pero funciona:
en lugar de escribir
import memberName from "path" + "fileName";
// this will not work!, since "path" + "fileName" need to be string literal
usa esta sintaxis:
let memberName = require("path" + "fileName");
No con la declaración de
import
.
import
y
export
se definen de tal manera que son analizadas estáticamente, por lo que no pueden depender de la información de tiempo de ejecución.
Está buscando la API del cargador (polyfill) , pero no estoy muy claro sobre el estado de la especificación:
System.import(''./utils/'' + variableName).then(function(m) {
console.log(m);
});
Si bien esto no es realmente una importación dinámica (por ejemplo, en mi circunstancia, todos los archivos que importo a continuación serán importados y agrupados por webpack, no seleccionados en tiempo de ejecución), un patrón que he estado usando que puede ayudar en algunas circunstancias es :
import Template1 from ''./Template1.js'';
import Template2 from ''./Template2.js'';
const templates = {
Template1,
Template2
};
export function getTemplate (name) {
return templates[name];
}
o alternativamente:
// 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;
No creo que pueda volver a un valor predeterminado tan fácilmente con
require()
, lo que arroja un error si intento importar una ruta de plantilla construida que no existe.
Puede encontrar buenos ejemplos y comparaciones entre require e import aquí: http://www.2ality.com/2014/09/es6-modules-final.html
Excelente documentación sobre reexportación de @iainastacio: http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles
Estoy interesado en escuchar comentarios sobre este enfoque :)
puede usar la notación no ES6 para hacer eso. Esto es lo que funcionó para mí:
let myModule = null;
if (needsToLoadModule) {
myModule = require(''my-module'').default;
}
La importación dinámica () (disponible en Chrome 63+) hará su trabajo. Así es cómo:
let variableName = ''test.js'';
let utilsPath = ''./utils/'' + variableName;
import(utilsPath).then((module) => { module.something(); });