ES6 variable import name in node.js?

2019-01-02 17:58发布

is it possible to import something into module providing variable name while using ES6 import?

I.e. I want to import some module at a runtime depending on values provided in a config:

import something from './utils/' + variableName;

7条回答
柔情千种
2楼-- · 2019-01-02 18:27

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
查看更多
心情的温度
3楼-- · 2019-01-02 18:28

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:

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.

Good examples and comparisons between require and import can be found here: 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

I'm interested to hear feedback on this approach :)

查看更多
零度萤火
4楼-- · 2019-01-02 18:30

There is a new specification which is called a dynamic import for ES modules. Basically, you just call import('./path/file.js') and your good to go. The function returns a promise, which resolves with the module if the import was successful.

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

Major use cases include route based module importing for Polymer 3.0, React and Vue, which reduces download bandwidth because the bundles for the routes are only loaded when they're required.

Here's the proposed spec on Github.

Right now (January 2017) this feature is working in Chrome 62. The other major browsers are probably picking up this feature and implementing it down the line when ESmodules are fully supported.

Edit:
I should add that the spec requires imports to be statically analyzable, both the regular import as well as the dynamic import, which means that you can't use a variable name to declare your import path. So there is no solution to your question because the ES spec prevents this by design.

查看更多
萌妹纸的霸气范
5楼-- · 2019-01-02 18:39

you can use the non-ES6 notation to do that. this is what worked for me:

let myModule = null;
if (needsToLoadModule) {
  myModule = require('my-module').default;
}
查看更多
闭嘴吧你
6楼-- · 2019-01-02 18:47

Not with the import statement. import and export are defined in such a way that they are statically analyzable, so they cannot depend on runtime information.

You are looking for the loader API (polyfill), but I'm a bit unclear about the status of the specification:

System.import('./utils/' + variableName).then(function(m) {
  console.log(m);
});
查看更多
孤独总比滥情好
7楼-- · 2019-01-02 18:52

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");
查看更多
登录 后发表回答