Proposal: importing selected chucks of a module into an object

# Norbert de Langen (8 years ago)

importing selected chucks of a module into an object

Modules are always imported into the root scope of the imported file. But in some cases it can be desirable to load modules into a namespace-object. Especially when importing a large number of parts/chunks from a module creating a separate variable for each become unwieldy.

There's a way to load the module as/into an object using this syntax:

import * as myLib from 'myLib';
 
// usage
myLib.chunkA();

However, it’s impossible to load only certain chunks AND bundle the chucks into an object at the same time.

Currently an editor needs to do this:

import { chunkA, chunkB } from 'myLib';
const myLib = { chunkA, chunkB };
 
// usage
myLib.chunkA();

I propose this would be allowed:

import { chunkA, chunkB } as myLib from 'myLib';
 
// usage
myLib.chunkA();

This can become a useful tool when using multiple libraries with similar utility or namingschemes, for example:

import { parse } from 'xml-lib';
import { parse } from 'json-lib';
import { parse } from 'html-lib';
 
// usage
parse(); // :(

One of the ways this can currently be solved is like this:

import { parse as xmlParse } from 'xml-lib';
import { parse as jsonParse } from 'json-lib';
import { parse as htmlParse } from 'html-lib';
 
// usage
xmlParse();
jsonParse();
htmlParse();

Namespacing variables like this can be a valid strategy, but it can become cumbersome:

import { parse as xmlParse, create as xmlCreate, sandwich as xmlSandwich } from 'xml-lib';
import { parse as jsonParse, create as jsonCreate, bacon as jsonBacon } from 'json-lib';
import { parse as htmlParse, create as htmlCreate, orange as htmlOrange } from 'html-lib';

It would be nice to have this option:

import { parse } as xmlLib from 'xml-lib';
import { parse } as jsonLib from 'json-lib';
import { parse } as htmlLib from 'html-lib';
 
// usage
xmlLib.parse();
jsonLib.parse();
htmlLib.parse();

It would even be usable like this, though it's not likely to be needed:

import { parse as read } as xmlLib from 'xml-lib';
 
// usage
xmlLib.read();
# Tab Atkins Jr. (8 years ago)

On Tue, May 24, 2016 at 11:59 AM, Norbert de Langen <Norbert.de.Langen at macaw.nl> wrote:

It would be nice to have this option:

import { parse } as xmlLib from 'xml-lib';
import { parse } as jsonLib from 'json-lib';
import { parse } as htmlLib from 'html-lib';

// usage
xmlLib.parse();
jsonLib.parse();
htmlLib.parse();

This begs the question, tho - why do you only need to import selected chunks? If you're pulling in the module as a namespace object, how does having the rest of the module available harm you?

# Norbert de Langen (8 years ago)

I think there’s a preference reason for this but also optimization reasons.

For humans it becomes crystal clear exactly what parts are dependent on. I personally like this.

When importing the entire module the module code needs to be run to figure out what parts are not needed. Eliminating the possibility of tree-shaking I believe.

# Jordan Harband (8 years ago)

This is usually part of the reason why small modules are recommended, rather than large object bags of things (including many named exports). Have you considered putting each thing you want to import as the default export of a separate file?

# Norbert de Langen (8 years ago)

Small modules are great, especially for creators. I’m onboard with small-modules being the default and recommended way of doing things. But.. I think history has shown that there is a use-case and a place in the world for larger composed modules. Take a look at lodash or jQuery for example. From a consumer point of view larger / composed modules make a lot of sense. A ‘higher order module’ if you will. Here’s the author of roll-up making a case for such modules as well: medium.com/@Rich_Harris/small-modules-it-s-not-quite-that-simple-3ca532d65de4#.hczbjni3t

When dealing with many dependencies (for whatever reason) or just dependencies that are really related, it’s nice to not have to do this:

// small modules
import xmlParse from 'xml-parse';
import xmlCreate from 'xml-create';
import xmlSandwich from 'xml-sandwich';
import jsonParse from 'json-parse';
import jsonCreate from 'json-create';
import jsonBacon from 'json-bacon';
import htmlParse from 'html-parse';
import htmlCreate from 'html-create';
import htmlOrange from 'html-orange';

// over
import { parse, create, sandwich } as xmlUtil from 'xml-util';
import { parse, create, bacon } as jsonUtil from 'json-util';
import { parse, create, orange } as htmlUtil from 'html-util';

From: Jordan Harband <ljharb at gmail.com>

Date: dinsdag 24 mei 2016 21:23 To: Norbert Langen <Norbert.de.Langen at macaw.nl>

Cc: "Tab Atkins Jr." <jackalmage at gmail.com>, "es-discuss at mozilla.org" <es-discuss at mozilla.org>

Subject: Re: Proposal: importing selected chucks of a module into an object

This is usually part of the reason why small modules are recommended, rather than large object bags of things (including many named exports). Have you considered putting each thing you want to import as the default export of a separate file?

On Tue, May 24, 2016 at 9:20 PM, Norbert de Langen <Norbert.de.Langen at macaw.nl<mailto:Norbert.de.Langen at macaw.nl>> wrote:

I think there’s a preference reason for this but also optimization reasons.

For humans it becomes crystal clear exactly what parts are dependent on. I personally like this.

When importing the entire module the module code needs to be run to figure out what parts are not needed. Eliminating the possibility of tree-shaking I believe.

# Isiah Meadows (8 years ago)

Even with some larger libraries, you can do things like this:

// small modules

import xmlParse from 'xml/parse';
import xmlCreate from 'xml/create';
import xmlSandwich from 'xml/sandwich';

import jsonParse from 'json/parse';
import jsonCreate from 'json/create';
import jsonBacon from 'json/bacon';

import htmlParse from 'html/parse';
import htmlCreate from 'html/create';
import htmlOrange from 'html/orange';

Lodash is a good example of this - check out its lodash-es6 build, or the various examples using lodash/isArray, lodash/map, lodash/match, etc.

I'm of the school of thought that I'm fine using smaller modules, but why depend on foreach, array-map, and is-array separately when you can depend on lodash, and just import lodash/forEach, lodash/map, and lodash/isArray? If I can get the same functionality with fewer dependencies, using modules likely to be reused by other modules because the versions are compatible, I'm all for it. Even if it comes with extra stuff, that extra stuff won't make it into a Browserify or Rollup bundle.