1

Say I have a library structure as below:

my-library
|-- lib
|   |
|   |-- foo
|   |   |--index.js
|   |
|   |-- bar
|       |--index.js
|
|---src
|   |-- foo
|       |-- button.js
|       |-- index.js
|   |-- bar
|       |-- button.js
|       |-- index.js
|-- package.json

I want to import these packages like this:

import { button } from 'my-library/foo'
import { button } from 'my-library/bar'

Is this possible?

The only way I have got it working is to import it like:

import { Button } from 'my-library/lib/foo'

I'm using Babel if that helps. Should I just transpile to the root directory and not use a lib dir?

I'm was looking at packages that do this such as lodash and React Native Vector Icons where they specify what they are importing.

Similar question here: Root directory in package.json

Karl Taylor
  • 4,839
  • 3
  • 34
  • 62
  • 1
    yes, that's what index.js is for. Have index.js export everything you want to expose using `import ... from 'my-library/foo'`. Index.js should have a series of exports looking something like this `export { button } from './button.js'` – Adam H Feb 27 '19 at 15:38
  • @AdamH I've got a step further, but doesn't seem right – Karl Taylor Feb 27 '19 at 15:49

1 Answers1

1

ECMAScript modules (ES modules) support an experimental property in package.json called exports that allows submodule aliases.

Given a package.json file with this config:

{
  "name": "my-library",
  "exports": {
    "./foo/": "./lib/foo/",
    "./bar/": "./lib/bar/"
  }
}

You should be able to import modules like:

import { button } from 'my-library/foo'
import { button } from 'my-library/bar'

Another option is to update your build script:

  • copy ./my-library/package.json over to ./my-library/lib/package.json
  • update the main field if needed
  • publish from the ./my-library/lib directory

Regarding updating the main field, you might want to consider adding a ./my-library/lib/index.js file that exports every module from your library for consumers that want to import from a fixed path (however, in a browser environment this would increase their bundle size):

import { button } from 'my-library'
morganney
  • 6,566
  • 1
  • 24
  • 35