Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

npm package.json main and project structure

I have a issue with npm and the main field. I see the documentation and as of my understanding I point main to be a different entry point than ./index.js. I already tested the package where all dist files are inside the root folder. I ignore src and test during pack phase using .npmignore but I did not like the point that building and packing the project to verify the structure pul all my files into the package root folder. So i changed the output to be dist instead.

If i use npm pack and extract the file I get the following structure:

/
dist
  -- index.js
  -- moduleA
    -- index.js
package.json
README.md

So for so good. But now I am forced to import it as follows:

import {moduleA} from "myNpmModule/dist/moduleA";

But I dont want to have the dist folder in my import. So I set main in package.json

"main": "dist/index.js"

But still it does not work and only works if I import with dist. I use npm 3.10.7 and node 6.7.0.

Can anyone help?

Regards

like image 219
jonas.hartwig Avatar asked Sep 28 '16 09:09

jonas.hartwig


1 Answers

It's hard to tell for sure not knowing the contents of your main index.js and moduleA but it's usually done in a way that you don't import any specific file, but rather the directory containing the package.json - like:

import {moduleA} from "myNpmModule";

Now, the index.js referenced as "main" in package.json should import the rest of the modules, and export them as its own module.exports properties.

For example, in dist/index.js:

import {moduleA} from "./moduleA";
module.exports.moduleA = moduleA;

and in your main code:

import {moduleA} from "myNpmModule";

Something like that - with possible differences to suits your own module's structure.

Actually I wrote a module that automatically does something like that, importing modules in subdirectories and exporting them as properties. I haven't put it on npm because it was for my own use, when I publish it to npm I'll update this answer.

Update

Here is a working example of what I described above - with import changed to require() to avoid the need for a transpilation step.

Module

A module following my advice from this answer:

  • https://github.com/rsp/node-nested-project-structure-example

Project structure:

dist
  -- index.js
  -- moduleA
    -- index.js
package.json
moduleA.js

dist/index.js contents:

var {moduleA} = require('./moduleA');
module.exports.moduleA = moduleA;

dist/moduleA/index.js contents:

module.exports.moduleA = {
  info: 'This is what dist/moduleA/index.js exports as moduleA'
};

package.json contents:

{
  "name": "nested-project-structure-example",
  "version": "0.0.1",
  "description": "An example for a Stack Overflow answer",
  "main": "dist/index.js",
  "scripts": {
    "test": "node test.js"
  },
  // ...
}

moduleA.js contents:

module.exports = require('./dist/moduleA');

Usage

A project that uses this module:

  • https://github.com/rsp/node-nested-project-structure-usage

It can be imported like this:

Version 1
var {moduleA} = require('nested-project-structure-example');
console.error(moduleA.info);

This imports the dist/ModuleA/index.js via the dist/index.js file referenced in package.json. See test1.js for a working example.

Version 2
var {moduleA} = require('nested-project-structure-example/dist/moduleA');
console.error(moduleA.info);

This imports the dist/ModuleA/index.js directly knowing the internal path including dist. See test2.js for a working example.

Version 3
var {moduleA} = require('nested-project-structure-example/moduleA');
console.error(moduleA.info);

This imports the dist/ModuleA/index.js via the moduleA.js file in the main project directory. That way doesn't need to know the internal project organization - dist path is not needed. See test3.js for a working example.

The whole content of the moduleA.js in the project is:

module.exports = require('./dist/moduleA');

Without having such a file in your project's root directory you will not be able to import the moduleA without either including the dist in your path or importing it directly via the main js file of your project included in package.json (dist/index.js in this case).

Those are 3 ways to achieve the goal of your question, two of which don't include the dist in the code that imports the module. I hope it answers your question.

Those are the only options that you have without splitting your module into a set of completely separate modules, each distributed separately.

like image 95
rsp Avatar answered Sep 20 '22 23:09

rsp