0

TL;DR How do I configure different "sub-modules" in a modular node.js project to refer to one another as simply as possible?

I'm trying to wrap my head around local packages for NPM, specifically as they relate to a modular project.

I'm building a web app with a front end and a back end API. These need to share a package which exports simple models. My project directory structure looks like this:

package
├── api
│   ├── dist
│   │   └── <compiled files>
│   ├── node_modules
│   │   └── ...
│   ├── package.json
│   └── src
│       └── <source files>
├── application
│   ├── dist
│   │   └── <compiled files>
│   ├── node_modules
│   │   └── ...
│   ├── package.json
│   └── src
│       └── <source files>
└── models
    ├── dist
    │   └── <compiled files>
    ├── node_modules
    │   └── ...
    ├── package.json
    └── src
        └── <source files>

Both the API and application projects are going to use models, so I abstracted that code to a separate sub-module within my project.

I've read the documentation for npm link and that seems to be the right approach because, as I understand it, it symlinks the package in the node_modules dir. This gives access to the code as it exists right now, instead of installing a copy in node_modules. Sounds like what I need, but there is a wrinkle: I'm working on this project from a couple of different places: my laptop, my office at work, and occasionally from home. In addition, others will be contributing to this project in the future.

I would like to make it as simple as possible for a new contributor to get up and running with development.

Currently, a new contributor goes through these steps:

  1. clone the repository
  2. cd into the models dir
    1. run npm install
    2. npm link
  3. cd into the api dir
    1. run npm install
    2. npm link models
  4. cd into the application dir
    1. run npm install
    2. npm link models
  5. start working

What I would like to do (and I think npm should be capable of doing) is:

  1. clone the repository
  2. cd into the models dir
    1. run npm install
  3. cd into the api dir
    1. run npm install
  4. cd into the application dir
    1. run npm install
  5. start working

I could write a script to do this, but it seems like an obvious use case for npm and I suspect that it's probably capable of doing something like this. I think I may be overlooking something because I'm not finding it in the documentation.

Kryten
  • 15,230
  • 6
  • 45
  • 68
  • Is it really needed to have three separate `package.json`? Shouldn't you only create a main `json` file? I haven't been in a situation where it is a need yet – Omar Vazquez Mar 01 '17 at 15:32
  • Why? NPM already does deduplication for you. If this is one project you don't need three package.json files, just use a single one. On the other hand, if these are three different projects that are independent and can be published each in their own right, then good news: npm will already automatically do link based deduplication for you. – Mike 'Pomax' Kamermans Mar 01 '17 at 15:42
  • Re: multiple package.json files - ultimately, this code will be run in multiple docker containers and I was looking for a way to ensure that unnecessary dependencies are installed. For example, if the API container needs a dependency that the application container does not, this seemed like the simplest way to avoid installing it where it's not needed. – Kryten Mar 03 '17 at 17:46

1 Answers1

1

There may be better ways to solve this, but..

One possibility is to create a package.json in the root of your project, which handles all of the initialization of your project.

package
├── package.json

And the contents of the package.json has no dependencies, but scripts to link and install dependencies for all of the submodules using just npm install from the package directory.

If you put the following in a package.json in your package folder

{
  "name": "package-name",
  "version": "1.0.0",
  "description": "Some description",
  "scripts": {
    "init-models": "cd ./models && npm install && npm link",
    "init-api": "cd ./api && npm install && npm link",
    "init-app": "cd ./application && npm install && npm link",
    "postinstall": "npm run init-models && npm run init-api && npm run init-app"
  }
}

You will just need to npm install to initialize the whole project.

JAM
  • 6,045
  • 1
  • 32
  • 48