Pass options to ES6 module imports

JavascriptModuleEcmascript 6Es6 Modules

Javascript Problem Overview


Is it possible to pass options to ES6 imports?

How do you translate this:

var x = require('module')(someoptions);

to ES6?

Javascript Solutions


Solution 1 - Javascript

There is no way to do this with a single import statement, it does not allow for invocations.

So you wouldn't call it directly, but you can basically do just the same what commonjs does with default exports:

// module.js
export default function(options) {
    return {
        // actual module
    }
}

// main.js
import m from 'module';
var x = m(someoptions);

Alternatively, if you use a module loader that supports monadic promises, you might be able to do something like

System.import('module').ap(someoptions).then(function(x) {
    …
});

With the new import operator it might become

const promise = import('module').then(m => m(someoptions));

or

const x = (await import('module'))(someoptions)

however you probably don't want a dynamic import but a static one.

Solution 2 - Javascript

Concept

Here's my solution using ES6

Very much inline with @Bergi's response, this is the "template" I use when creating imports that need parameters passed for class declarations. This is used on an isomorphic framework I'm writing, so will work with a transpiler in the browser and in node.js (I use Babel with Webpack):

./MyClass.js

export default (Param1, Param2) => class MyClass {
    constructor(){
        console.log( Param1 );
    }
}

./main.js

import MyClassFactory from './MyClass.js';

let MyClass = MyClassFactory('foo', 'bar');

let myInstance = new MyClass();

The above will output foo in a console

EDIT

Real World Example

For a real world example, I'm using this to pass in a namespace for accessing other classes and instances within a framework. Because we're simply creating a function and passing the object in as an argument, we can use it with our class declaration likeso:

export default (UIFramework) => class MyView extends UIFramework.Type.View {
    getModels() {
        // ...
        UIFramework.Models.getModelsForView( this._models );
        // ...
    }
}

The importation is a bit more complicated and automagical in my case given that it's an entire framework, but essentially this is what is happening:

// ...
getView( viewName ){
    //...
    const ViewFactory = require(viewFileLoc);
    const View = ViewFactory(this);
    return new View();
}
// ...

I hope this helps!

Solution 3 - Javascript

Building on @Bergi's answer to use the debug module using es6 would be the following

// original
var debug = require('debug')('http');

// ES6
import * as Debug from 'debug';
const debug = Debug('http');

// Use in your code as normal
debug('Hello World!');

Solution 4 - Javascript

I've landed on this thread looking up for somewhat similar and would like to propose a sort of solution, at least for some cases (but see Remark below).

Use case

I have a module, that is running some instantiation logic immediately upon loading. I do not like to call this init logic outside the module (which is the same as call new SomeClass(p1, p2) or new ((p1, p2) => class SomeClass { ... p1 ... p2 ... }) and alike).

I do like that this init logic will run once, kind of a singular instantiation flow, but once per some specific parametrized context.

Example

service.js has at its very basic scope:

let context = null;                  // meanwhile i'm just leaving this as is
console.log('initialized in context ' + (context ? context : 'root'));

Module A does:

import * as S from 'service.js';     // console has now "initialized in context root"

Module B does:

import * as S from 'service.js';     // console stays unchanged! module's script runs only once

So far so good: service is available for both modules but was initialized only once.

Problem

How to make it run as another instance and init itself once again in another context, say in Module C?

Solution?

This is what I'm thinking about: use query parameters. In the service we'd add the following:

let context = new URL(import.meta.url).searchParams.get('context');

Module C would do:

import * as S from 'service.js?context=special';

the module will be re-imported, it's basic init logic will run and we'll see in the console:

initialized in context special

> Remark: I'd myself advise to NOT practice this approach much, but leave it as the last resort. Why? Module imported more than once is more of an exception than a rule, so it is somewhat unexpected behavior and as such may confuse a consumers or even break it's own 'singleton' paradigms, if any.

Solution 5 - Javascript

I believe you can use es6 module loaders. http://babeljs.io/docs/learn-es6/

System.import("lib/math").then(function(m) {
  m(youroptionshere);
});

Solution 6 - Javascript

You just need to add these 2 lines.

import xModule from 'module';
const x = xModule('someOptions');

Solution 7 - Javascript

Here's my take on this question using the debug module as an example;

On this module's npm page, you have this:

var debug = require('debug')('http')

In the line above, a string is passed to the module that is imported, to construct. Here's how you would do same in ES6

import { debug as Debug } from 'debug'

const debug = Debug('http');

Hope this helps someone out there.

Solution 8 - Javascript

I ran into an analogous syntax issue when trying to convert some CJS (require()) code to ESM (import) - here's what worked when I needed to import Redis:

CJS

const RedisStore = require('connect-redis')(session);

ESM Equivalent

import connectRedis from 'connect-redis';
const RedisStore = connectRedis(session);

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
QuestionFabrizio GiordanoView Question on Stackoverflow
Solution 1 - JavascriptBergiView Answer on Stackoverflow
Solution 2 - JavascriptSwivelView Answer on Stackoverflow
Solution 3 - JavascriptmummybotView Answer on Stackoverflow
Solution 4 - JavascriptGullerYAView Answer on Stackoverflow
Solution 5 - Javascriptuser895715View Answer on Stackoverflow
Solution 6 - JavascriptMansi TehariaView Answer on Stackoverflow
Solution 7 - JavascriptAkinwale Folorunsho HabibView Answer on Stackoverflow
Solution 8 - JavascripttonetharView Answer on Stackoverflow