Build modular application with npm local modules

Rationale

Arnaud Rinquin
2 min readMay 6, 2015

EDIT: I just released rm_local_modules, a really simple module best used as a npm preinstall script so you can quickly update (delete + reinstall) all your local modules simply. Problem is, npm 3 preinstall is broken.

Most large javascript application built using npm modules have the same problem: tons of javascript files stored in deeply nested folders.

You will definitely end up with ugly require such as

var User = require(‘../../../../models/User’);

This sucks. Relative requires do not scale well. What you want instead is:

var User = require(‘app-models’).User;

Hey but that means I need to publish my module, use private modules or host it on a separate git repo?!

Nope.

Solution

npm supports a variety of ways to declare module dependencies, the least known being the local one.

Using local modules, here is what your package.json can look like:

{
“name”: “my-app”,
“dependencies”: {
“lodash”: “^2.0.0”,
“my-module”: “file:local_modules/my-module”,
}
}

That’s about it. Simply declare the path to your local module, prefixed with “file:”.

You can even npm install them and have the package.json written for you:

npm install --save ./path_to_my/custom_module

This will copy your local module into the node_modules folder, the same way it would do with a repository or git hosted module.

Obviously, this means your local module should have its own package.json, README.md, etc, like any regular node module.

This also means that you need to update your node_module copy every time you modify your original code. This can be achieved by:

rm -rf node_module/custom_module && npm install

which is easy when you are working on the custom module,

Or, use rm-local-modules to remove all of them automatically

// package.json
{
“devDependencies”: {
“rm-local-modules”: “0.0.1”
},
“scripts”: {
“preinstall”: “rm-local-modules”
}
}

but the cleaner way to update it is by bumping its package.json version and running npm update

Additional benefits

You have to force yourself writing coherent, self contained, decoupled modules. That’s a good thing.

You realised some of your submodule could be a 3rd party library, you think about publishing it. Cool! That is now super easy as you already have a module structure, including its own package.json, and your app uses it the same way it would if the module was published. Just move it to its own repo, publish, change your app dependency, profit. No code refactor involved.

Example

Just play with this simple repo: https://github.com/ArnaudRinquin/local_modules_poc

Caveats

npm 3+ handling of preinstall script is broken, therefore using rm-local-modules won’t work properly for now. Works fine on npm 2.

--

--

Arnaud Rinquin

Random dude on internet. I develop web things sometimes. Mostly Javascript related.