Skip to content

Instantly share code, notes, and snippets.

@twilson63
Created February 28, 2014 18:42
Show Gist options
  • Save twilson63/9277035 to your computer and use it in GitHub Desktop.
Save twilson63/9277035 to your computer and use it in GitHub Desktop.

NPM = {rubygems + gembundler}

Npm is the node package manager and it is a repository of packages that can be downloaded and incorporated into your application. Using the npm command-line tool you can install these packages on your system and specifically for your project. Just like gem install ... Npm has learned from some of the pain points in other package management systems and has made an improvement to how code modules are managed. If you live in the ruby world you may be familiar with gem and bundler, npm represents the merger of both of these tools.

The way I like to think of rubygems is an application registry of ruby open source and I think of bundler as a project manifest that describes all of your dependencies in a particular project. NPM does both, it is an interface to a registry and it provides a manifest in the package.json file. All module installations are installed local to the project in the node_modules folder. And node looks in that folder when you ask node to require a module. So if the module does not exist in the node_modules folder then node can only find it when you specify a path, like require('./foo') in this example, node will look for foo in the root directory of the project.

The nice thing about npm and node_modules, is that the manifest of a module and the manifest of the application is exactly the same, which makes it super easy to publish modules and it also makes it easy to break up your code base into feature based modules and maintain them in separate repositories.

This concept leads to well defined small pieces that make up large applications.

- project
  index.js
  - node_modules
    - module1
      - index.js
    - module2
      - index.js
    - module3
      - index.js
      - node_modules
        - index.js

By leveraging npm and using node_modules as your application structure it keeps your project organization simple and semantic.

Instead of having a complex application file structure:

- project
  - app
    - controllers
    - views
    - models
  - config
    - environments
      - production
      - staging
  - lib
    - tasks
  - logs
  - spec
  - features

...

You have a more simple and semantic approach that is just as conventional and perhaps easier to sort through.

- root - // Project Management Application
  - index.js // main file
  - package.json  // manifest file
  - node_modules
    - index.js
    - package.json
    - users  // users module 
      - node_modules
        - authentication
        - authorization
    - projects  // projects module
      - index.js
      - package.json
      - node_modules
        - tasks  // tasks module
          - index.js
          - package.json

So with the above structure, if I need to change or modify the tasks section, it is cleanly separated from all other areas of the application as well as each module can have its own test suite and ci integration, this keeps all the tests as fast as possible. End the end this offers a solid approach, because I can control dependencies and keep all of my wired up modules in the main app repo. Without the tight coupling of the MVC file structure.


So hopefully at this point, you are saying great! But, what about front-end. Well, the current popular tools are Grunt, Gulp, yo, and Bower, and these are fine, but what if you don't want to have to keep up with 4 build tool eco systems.

Introducing NAPA

Napa is a module that allows you to pull in bower or git repo's as node_modules, the effect of this, is that you can now add frontend frameworks and components to your node_modules list, instead of a separate manifest. I think this should be purely preference, but it you want to keep all of your pieces of the app in one common structure, the napa module is a great way to add angularjs and other front-end tooling into your app.

In your package.json, all you have to do is add a new node:

{
  "devDependencies": {
    "napa": "~0.4.0"
  },
  "napa": {
  	"angular": "angular/bower-angular",
    "ur-router": "angular-ui/ui-router"
  },
  "scripts": {
    "install": "napa"
  }
}

Questions?

Please email me at tom@jackhq.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment