Using Browserify without a node_modules directory
Posted on Sat 19 July 2014 in JavaScript
NPM and Bower are pretty awesome; they provides both NodeJS and web developers a way to share CommonJS modules (aka packages) amongst code-bases without relying on copy/pasting concatenated .js files. Browserify fills in the missing link for deploying an application to the web; it gathers up disparate CommonJS modules which NPM/Bower resolved and bundles them up into a single .js file ready to be dropped into a <script>
tag.
When writing CommonJS code, you can import files by two methods, either relativley, (typically used internally inside your app / module), ie:
var MakePizzaCommand = require("./commands/MakePizzaCommand");
Or you can import entire libraries, eg: those which were resolved by Bower / NPM
var reqwest = require("reqwest");
In the first example, Browserify will locate the MakePizzaCommand
object by reading the file relative from the host file making the require
call; ie:
├── app.js <-- makes the require call
└── commands
└── MakePizzaCommand.js <-- gets included
In the second example, Browserify identifies that you are not referencing a local file (as the require
argument does not look like a path), so instead it starts looking up the directory tree for a node_modules
folder which contains a subfolder for the module the host file making the require call is trying to import.
pizzajs
├── node_modules <-- 3. found it! now look in each subfolder
│ │ for a package.json file with the name of
│ │ the module we are trying to import.
│ └── reqwest
│ └── package.json
│
├── src <-- 2. no `node_modules` dir here either, so look in the
│ │ parent dir (pizzajs)
│ │
│ ├── app.js <-- 1. makes the require call, no `node_modules` dir
│ │ here so look in parent dir (src)
│ └── commands
│ └── MakePizzaCommand.js
└── test
But what if you don't want to use NPM / Bower to resolve your dependencies? AFAIK you have two options avaiable to you:
-
Create a
node_modules
folder in your project and copy all your CommonJS libraries into it during the build process; note that thenode_modules
folder must sit either adjacent to your project's sources (src
) or in a ancestor folder. -
Make use of the
NODE_PATH
environment variable, this provides another absolute URL for browserify to use when looking for CommonJS modules. This allows you to pull off the following folder structure (which may suit none-javascript-based build systems better):
pizzajs
├── lib
│ └── reqwest
│ └── package.json
└── src
└── app.js
If you're using Grunt, you can easily set the NODE_PATH
environment variable with each build by adding the following to the top of your Gruntfile.js
:
// Set NODE_PATH env-var to the cwd.
process.env["NODE_PATH"] = __dirname;
module.exports = function(grunt) {
grunt.initConfig({ .. });
});