3

I would like to combine some modules into a single file that can be imported. These are local files and not part of an npm module.

Module Kitten (kitten.js)

export function Feed() {}
export function Play() {}

In my code I can access 'Feed' and 'Play':

// This works but I would like to avoid this due to my paths
import { Feed, Play } from './some/long/path/kitten.js'

// Then use it
Feed()

As I have many 'pets' I can contenate them in a master file - say pets.js

export * as Kitten from './some/long/path/kitten.js'
export * as Puppies from './some/long/path/puppies.js'
...

In my code I can then do:

import { Kitten, Puppies } from './pets'

// Then use it as
Kitten.Feed()

is it possible to have both a) the master pets file and b) call Feed() without doing Kitten.Feed()?

The following doesn't work as it's not a valid path. It's possible it would work as 'pets/Kitten' if it was an npm module - am not sure.

import { Feed, Play } from './pets/Kitten'

I was thinking something along the lines of:

import * as Pets from from './pets'
import { Feed, Play } from Pets.Kitten // or 'Pets/Kitten'

But clearly that doesn't work. I am wondering if it's at all possible.

I am using this in Node with Babel 6 and ES6 module loading. I see a lot of similar questions but they all use default exports which I am not using.

cyberwombat
  • 38,105
  • 35
  • 175
  • 251
  • 1
    Python community will give u answer.. wait 3 min at most – Abdennour TOUMI Aug 03 '16 at 20:21
  • 2
    Instead of `export default { Puppy, Kitten }` couldn't you just do `export Puppy; export Kitten`? – gcampbell Aug 03 '16 at 20:34
  • @gcampbell - trying variations but no go – cyberwombat Aug 03 '16 at 20:41
  • FYI, the module loader is not part of ES6. If you run the code in Node for example, then you are using Node's module loader. You can read about it how it works: https://nodejs.org/api/modules.html – Felix Kling Aug 03 '16 at 21:33
  • @FelixKling I am aware of this. I am using the ES6 module loader as handled by Babel 6 and my question should be tagged accordingly – cyberwombat Aug 03 '16 at 22:02
  • Babel6 only transpiles your code, it doesn't do any module loading. All it does is converting `import Foo from 'bar';` into `var Foo = require('bar');`. – Felix Kling Aug 03 '16 at 22:03
  • I am not sure what you are asking, but it sounds like a duplicate of [import modules from files in directory](http://stackoverflow.com/q/29722270/1048572) – Bergi Aug 04 '16 at 00:27
  • @Bergi - not the same - they have default exports. I think I will close this question and look at the RxJS code to see how they did it. – cyberwombat Aug 04 '16 at 01:01
  • @Yashua: It's [possible with default exports](http://stackoverflow.com/q/34072598/1048572) just as well – Bergi Aug 04 '16 at 01:13

2 Answers2

1

But that doesn't allow me to import selected functions.

Sure it does. The relative-path import works the same as module import. You can destructure the results just the same.

import { Play } from 'Pet/Puppy';
// is identical to
import { Play } from '../node_modules/Pet/Puppy';

If you take a look at the import syntax (s15.2.2), you can see that the from part expects a string. It doesn't care what's in the string, that's up to the module system (the browser, node, etc).

ssube
  • 47,010
  • 7
  • 103
  • 140
  • In the first case you must have it as an npm module correct? The second won't work for me really as the point of concatenating is that my subfiles have complex path so i am looking for a one entry file. – cyberwombat Aug 03 '16 at 20:27
  • The first syntax is for including a file from a module, yeah. When you concatenate, the result won't have any paths, it will replace the `import` (or `require`) with a reference to the module from the same file. – ssube Aug 03 '16 at 20:35
  • Ok. So if I understand correctly the answer to my question is "no way - unless you publish it as a module"? – cyberwombat Aug 03 '16 at 20:42
  • Not at all. You can absolutely import and re-export symbols from a local file. Once you concatenate the files in your module, you're simply exporting the symbol like normal (without needing to import it). – ssube Aug 03 '16 at 20:44
  • I'm sorry for being obtuse but how? We agree that example #1 is not possible without publishing and #2 won't work (or is not manageable) due to the complex path. You have `'../node_modules/Pet/Puppy` which assumes a file called Puppy. I tried in hopes that it would guess I wanted the exported 'Puppy' module but it just throws errors about files not found – cyberwombat Aug 03 '16 at 20:50
  • The second option *will* work, that's how we bundle exports in libraries. I'm using something almost identical [here](https://github.com/ssube/noicejs/blob/master/src/main/inject.js#L8) and it works just fine. Your concatenation tool need to replace the path with a reference, that's all. That's how browserify and webpack and every other tool I'm aware of handles it (more or less). – ssube Aug 03 '16 at 20:54
  • I just tried your code with same errors: https://gist.github.com/429542e01c45c46d79739e3a38b94d95 - Cannot find module './inject/Injector' – cyberwombat Aug 03 '16 at 21:01
  • What does your build process look like? If it's an extensive explanation, we can [take it over to chat](http://chat.stackoverflow.com/rooms/17). – ssube Aug 03 '16 at 21:05
  • No build process. NodeJS Babel transpiling on the fly with babel-node – cyberwombat Aug 03 '16 at 21:42
  • That's definitely part of your problem. You need to use a concatenation tool that's aware of modules or make sure the relative paths remain valid. – ssube Aug 04 '16 at 14:37
1

Ah.. object destructuring.. Forgot about that.

import { Kitten, Puppies } from './pets'
const {Feed, Play} = Kitten;

Thanks to https://stackoverflow.com/a/30132149/856498

Community
  • 1
  • 1
cyberwombat
  • 38,105
  • 35
  • 175
  • 251