On a project I'm working on, we found ourselves needing to share code between two Javascript projects. There are several ways to accomplish this, the most common approach seems to be to use git submodules which people either love or hate. I wanted something easier to use and understand, so I decided to try out private NPM modules. Now that Meteor is NPM-friendly, this is finally a feasible option on Meteor projects.
Before we begin, a subscription (starting at $7/month) is required in order to use private packages with NPM. If you don't have that, then the rest of this article is kinda pointless, so I'll wait for you to go sign up: https://www.npmjs.com/pricing. Go ahead, I'll wait.
All signed up? Good. Let's proceed.
Creating the Module
To demonstrate how to use private modules, let's first create one. Create a new folder called stringUtils. Every project has one—a file that contains a bunch of utility functions for parsing or formatting strings. By moving it into a private package we can share that logic across all of our javascript projects. This private package can have dependencies (on moment.js, etc), and our main project would only have our new package as a dependency. That way we could swap out implementations of any of these methods (swap moment.js for something else, etc) and we wouldn't have to change a bunch of dependencies in all of our main projects, only in our private package. In our new folder create a package.json and use the following structure. Edit the name field "name": "@yourUserName/string-utils", and replace yourUserName with the username you signed up for at NPM. In my case, that would end up being "name": "@didevshop/string-utils", since didevshop is my username.
Another note: package names cannot contain uppercase letters!
// package.json
{
"name": "@yourUserName/string-utils",
"version": "1.0.0",
"description": "Common String Utils",
"main": "index.js"
}
Note the @yourUserName/string-utils. The @yourUserName part is its scope and it is how you will always refer to your new package. Private modules are 'scoped,' so instead of just running npm install string-utils , run npm install @yourUserName/string-utils.
Now create the index.js in our folder and paste the following:
// index.js
'use strict';
module.exports = {
currency: function(number) {
//super naive currency function
return `$${number}`;
}
};
Requires NPM 2.7
Before we can publish or use private modules we need to check our NPM version. Private modules are still semi-new and if you're like me you don't upgrade your NPM that often so let's check our NPM version by running npm -v. If it's below 2.7, then upgrade by running sudo npm install -g npm. If it's at or above 2.7, then you're good.
You need to login first
In order to publish or pull private modules, you'll need to login with the username/password you registered on https://www.npmjs.com using npm login in the terminal.
Let's publish it
Now we're ready to push our module to NPM. Run npm publish. Hopefully, you get a success message and if you log into https://www.npmjs.com and view your profile you should see your shiny new private module (with a lock symbol next to it to signify it's private).

Add it to our project
You should still be logged in with NPM (in your terminal), if not, this command will fail and you'll need to login. To add your new private module to your project, just go to the root of your meteor app and run npm install --save @didevshop/string-utils (replace didevshop with your username!!). The --save tells NPM to add the module to your package.json so if that commands succeeds (which it should if you're logged in) you should be able to open your package.json now and see your new package:
"dependencies": {
"@didevshop/string-utils": "^1.0.0"
}
Using your new package
Now that you've pulled your private module into your project to use it, just import it wherever you need to use it:
//replace didevshop with your username
// you don't have to use the variable name StringUtils, you
// can use whatever you want (like s)
import StringUtils from '@didevshop/string-utils';
//react example
class Price extends React.Component {
render() {
return <span>{StringUtils.currency(this.props.price)}</span>;
}
}
Bam, done! Now you can share versioned code between your projects privately and easily.
Updating your package
Updating the package is just as easy.
- Make your edits
- Bump the version number in package.json
- Run npm publish
NPM will keep all versions of your package on its server so you can incrementally upgrade all of your main projects that utilize it. Now as homework, replace that ugly currency function with something more useful and republish out to npm!