[英]ES6 variable import name in node.js?
is it possible to import something into module providing variable name while using ES6 import?是否可以在使用 ES6 导入时将某些内容导入提供变量名的模块中?
Ie I want to import some module at a runtime depending on values provided in a config:即我想根据配置中提供的值在运行时导入一些模块:
import something from './utils/' + variableName;
Not with the import
statement.不带
import
语句。 import
and export
are defined in such a way that they are statically analyzable, so they cannot depend on runtime information. import
和export
的定义方式使得它们可以静态分析,因此它们不能依赖于运行时信息。
You are looking for the loader API (polyfill) , but I'm a bit unclear about the status of the specification:您正在寻找loader API (polyfill) ,但我对规范的状态有点不清楚:
System.import('./utils/' + variableName).then(function(m) {
console.log(m);
});
Whilst this is not actually a dynamic import (eg in my circumstance, all the files I'm importing below will be imported and bundled by webpack, not selected at runtime), a pattern I've been using which may assist in some circumstances is:虽然这实际上不是动态导入(例如,在我的情况下,我在下面导入的所有文件都将由 webpack 导入和捆绑,而不是在运行时选择),但我一直在使用的一种模式在某些情况下可能会有所帮助是:
import Template1 from './Template1.js';
import Template2 from './Template2.js';
const templates = {
Template1,
Template2
};
export function getTemplate (name) {
return templates[name];
}
or alternatively:或者:
// 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;
I don't think I can fall back to a default as easily with require()
, which throws an error if I try to import a constructed template path that doesn't exist.我不认为我可以使用
require()
轻松地回退到默认值,如果我尝试导入不存在的构造模板路径,则会引发错误。
Good examples and comparisons between require and import can be found here: http://www.2ality.com/2014/09/es6-modules-final.html可以在此处找到 require 和 import 之间的良好示例和比较: http ://www.2ality.com/2014/09/es6-modules-final.html
Excellent documentation on re-exporting from @iainastacio: http://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles从@iainastacio 重新导出的优秀文档: http ://exploringjs.com/es6/ch_modules.html#sec_all-exporting-styles
I'm interested to hear feedback on this approach :)我很想听听关于这种方法的反馈:)
In addition to Felix's answer , I'll note explicitly that this is not currently allowed by the ECMAScript 6 grammar :除了Felix 的回答之外,我还要明确指出ECMAScript 6 语法目前不允许这样做:
ImportDeclaration :
进口声明:
import ImportClause FromClause ;
导入ImportClause FromClause ;
import ModuleSpecifier ;
导入模块说明符;
FromClause :
从句:
- from ModuleSpecifier
来自模块说明符
ModuleSpecifier :
模块说明符:
- StringLiteral
字符串字面量
A ModuleSpecifier can only be a StringLiteral , not any other kind of expression like an AdditiveExpression . ModuleSpecifier只能是StringLiteral ,不能是AdditiveExpression等任何其他类型的表达式。
There is a new specification which is called a dynamic import for ES modules.有一个新规范称为 ES 模块的动态导入。 Basically, you just call
import('./path/file.js')
and you're good to go.基本上,您只需调用
import('./path/file.js')
就可以了。 The function returns a promise, which resolves with the module if the import was successful.该函数返回一个promise,如果导入成功,该promise 将与模块一起解析。
async function importModule() {
try {
const module = await import('./path/module.js');
} catch (error) {
console.error('import failed');
}
}
Use-cases include route based component importing for React, Vue etc and the ability to lazy load modules , once they are required during runtime.用例包括为 React、Vue 等导入基于路由的组件,以及在运行时需要时延迟加载模块的能力。
Here's is an explanation on Google Developers .这是对Google Developers的解释。
According to MDN it is supported by every current major browser (except IE) and caniuse.com shows 87% support across the global market share.据MDN称,当前所有主流浏览器(IE 除外)都支持它,而caniuse.com在全球市场份额中的支持率为 87%。 Again no support in IE or non-chromium Edge.
同样不支持 IE 或非 Chromium Edge。
I understand the question specifically asked for ES6 import
in Node.js, but the following might help others looking for a more generic solution:我了解在 Node.js 中专门针对 ES6
import
提出的问题,但以下内容可能会帮助其他人寻找更通用的解决方案:
let variableName = "es5.js";
const something = require(`./utils/${variableName}`);
Note if you're importing an ES6 module and need to access the default
export, you will need to use one of the following:请注意,如果您要导入 ES6 模块并需要访问
default
导出,则需要使用以下选项之一:
let variableName = "es6.js";
// Assigning
const defaultMethod = require(`./utils/${variableName}`).default;
// Accessing
const something = require(`./utils/${variableName}`);
something.default();
You can also use destructuring with this approach which may add more syntax familiarity with your other imports:您还可以通过这种方法使用解构,这可能会增加您对其他导入的语法熟悉:
// Destructuring
const { someMethod } = require(`./utils/${variableName}`);
someMethod();
Unfortunately, if you want to access default
as well as destructuring, you will need to perform this in multiple steps:不幸的是,如果您想访问
default
和解构,则需要分多个步骤执行此操作:
// 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;
you can use the non-ES6 notation to do that.你可以使用非 ES6 符号来做到这一点。 this is what worked for me:
这对我有用:
let myModule = null;
if (needsToLoadModule) {
myModule = require('my-module').default;
}
I less like this syntax, but it work:我不太喜欢这种语法,但它有效:
instead of writing而不是写
import memberName from "path" + "fileName";
// this will not work!, since "path" + "fileName" need to be string literal
use this syntax:使用这个语法:
let memberName = require("path" + "fileName");
Dynamic import() (available in Chrome 63+) will do your job. 动态 import() (在 Chrome 63+ 中可用)将完成您的工作。 Here's how:
就是这样:
let variableName = 'test.js';
let utilsPath = './utils/' + variableName;
import(utilsPath).then((module) => { module.something(); });
I had similar problem using Vue.js
: When you use variable in import(variableName)
at build time Webpack doesn't know where to looking for.我在使用
Vue.js
时遇到了类似的问题:当您在构建时在import(variableName)
中使用变量时,Webpack 不知道在哪里寻找。 So you have to restrict it to known path with propriate extension like that:因此,您必须将其限制为具有适当扩展名的已知路径,如下所示:
let something = import("@/" + variableName + ".js")
That answer in github for the same issue was very helpful for me. github中针对同一问题的答案对我非常有帮助。
./utils/test.js ./utils/test.js
export default () => {
doSomething...
}
call from file从文件调用
const variableName = 'test';
const package = require(`./utils/${variableName}`);
package.default();
I would do it like this我会这样做
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
It depends.这取决于。 You can use template literals in dynamic imports to import a file based on a variable.
您可以在动态导入中使用模板文字来基于变量导入文件。
I used dynamic imports to add .vue
files to vue router.我使用动态导入将
.vue
文件添加到 vue 路由器。 I have excluded the Home.vue
view import.我已经排除了
Home.vue
视图导入。
const pages = [
'About',
['About', 'Team'],
]
const nodes = [
{
name: 'Home',
path: '/',
component: Home,
}
]
for (const page of pages) {
if (typeof page === 'string') {
nodes.push({
name: page,
path: `/${page}`,
component: import(`./views/${page}.vue`),
})
} else {
nodes.push({
name: _.last(page),
path: `/${page.join('/')}`,
component: import(`./views/${_.last(page)}.vue`)
})
}
}
This worked for me.这对我有用。 I was using yarn + vite + vue on replit.
我在 repli 上使用了 yarn + vite + vue。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.