ES6 variable import name in node.js?

Javascriptnode.jsEcmascript 6

Javascript Problem Overview


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;

Javascript Solutions


Solution 1 - Javascript

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);
});

Solution 2 - Javascript

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 :)

Solution 3 - Javascript

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

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

Use-cases include route based component importing for React, Vue etc and the ability to lazy load modules, once they are required during runtime.

Further Information

Here's is an explanation on Google Developers.

Browser compatibility (April 2020)

According to MDN it is supported by every current major browser (except IE) and caniuse.com shows 87% support across the global market share. Again no support in IE or non-chromium Edge.

Solution 4 - Javascript

In addition to Felix's answer, I'll note explicitly that this is not currently allowed by the ECMAScript 6 grammar:

> ImportDeclaration : > > * import 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.

Solution 5 - Javascript

I understand the question specifically asked for ES6 import in Node.js, but the following might help others looking for a more generic solution:

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:

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:

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

Solution 6 - Javascript

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

Solution 7 - Javascript

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");

Solution 8 - Javascript

Dynamic import() (available in Chrome 63+) will do your job. Here's how:

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

Solution 9 - Javascript

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. 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.

Solution 10 - Javascript

./utils/test.js

export default () => {
  doSomething...
}

call from file

const variableName = 'test';
const package = require(`./utils/${variableName}`);
package.default();

Solution 11 - Javascript

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVytautas ButkusView Question on Stackoverflow
Solution 1 - JavascriptFelix KlingView Answer on Stackoverflow
Solution 2 - JavascriptptimView Answer on Stackoverflow
Solution 3 - JavascriptNicolai SchmidView Answer on Stackoverflow
Solution 4 - JavascriptapsillersView Answer on Stackoverflow
Solution 5 - JavascriptMCTaylor17View Answer on Stackoverflow
Solution 6 - JavascriptmlevanonView Answer on Stackoverflow
Solution 7 - JavascriptGil EpshtainView Answer on Stackoverflow
Solution 8 - JavascriptVelojetView Answer on Stackoverflow
Solution 9 - JavascriptstanimirspView Answer on Stackoverflow
Solution 10 - JavascriptAndres MunozView Answer on Stackoverflow
Solution 11 - JavascriptaprilView Answer on Stackoverflow