Created
October 15, 2012 00:43
-
-
Save erithmetic/3890301 to your computer and use it in GitHub Desktop.
JS Packaging post
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
title: Client-Sdie JavaScript Packaging | |
author: derek | |
layout: post | |
categories: technology | |
--- | |
One of the joys of Ruby is its package manager, rubygems. With a simple `gem install` you can add a library to your app. There has been an explosion of JavaScript package managers lately. Each one adds the basic ability to gather all of your libraries and application code, resolve the dependencies, and concatenate them into a single application file. They can be grouped into three basic categories: | |
<!-- more start --> | |
### Simple concatenators | |
The earliest sorts of package managers, like [Sprockets](https://github.com/sstephenson/sprockets#readme) and [Stitch](https://github.com/maccman/stitch-rb) would require you to download release versions of libraries like jQuery and place them in your project. The concatenator would then prepend the library code before your application code. This approach lacks an automated process to download and update each library and requires static copies of each library in your application. | |
### Wrappers | |
Here, JavaScript libraries are wrapped inside other languages' packaging systems, like rubygems. This is the approach that Rails' [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html) and [BPM](http://getbpm.org/) take. The main disadvantage with this approach is that any JavaScript package you'd want to use would need a gem wrapper that would have to be kept up to date. Thus, only a few popular libraries like jQuery and underscore are available. | |
[Bower](http://twitter.github.com/bower/) (similar to [Volo](http://volojs.org/)) was recently released by the folks at Twitter. This system requires each library maintainer to define a component.json file in their project, leading to the same problem as above. | |
### Npm extensions | |
Many recent package managers piggyback on top of Node's npm/CommonJS module system. In the Node.js world, you can add packages to your application with the `npm install` command just as easily as with rubygems. It makes a lot of sense to use npm for client-side JavaScript package management. However, since not all npm packages will work in the browser (they may use V8 or Node.js-specific APIs), many of these piggybacked systems either restrict you to a subset of packages tagged specifically for that package manager, or they come with the caveat that you need to make sure all npm packages you use are client-side compatible. [Ender.js](http://ender.no.de/), Spine.js' [hem](http://spinejs.com/docs/hem), and most recently, [jam](http://jamjs.org/) are popular examples. | |
### Browserify - the transcendent package manager | |
I settled early on [browserify](https://github.com/substack/node-browserify) as my package manager of choice. It allows me to use npm modules in my app, just as if I was developing a Node.js app. Browserify adds a compatibility layer to your client side code, so that any calls to Node-specific APIs work in the browser. This means any package written for Node will work in the browser (with the exception of packages using file system and socket libraries). There is a plethora of modules that I use regularly, like `JSONPath` for JSON processing, `replay` for mocking HTTP (AJAX) requests (similar to Ruby's [vcr](https://www.relishapp.com/myronmarston/vcr/v/2-2-5/docs/)), and `async` for simplified asynchronous flow control. | |
Browserify brings node's CommonJS module system to the browser. It will encourage you to organize your code into CommonJS modules. | |
The disadvantage of a "pure" CommonJS approach is that many client-side libraries are written with global `window` and `document` objects in mind. You can stub these out in your test helper using jsdom. The other disadvantage is that a library you need may not be published as an npm package. I haven't yet run into this problem (in fact, I've found more packages on npm than I knew existed), but browserify can be configured to include any static library files you need. | |
#### Bundler-like dependency management | |
A typical Ruby gem or Rails app uses bundler to define and load dependencies. In the JavaScript world (using browserify), this can be done with npm. Simply place a `package.json` file in your application's root as if you were developing an npm module. In that file, add "dependencies" and "devDependencies" keys that list each npm package and version your app needs. On the command line, use `npm install` to install them. That's it, no special, client-side package manager-specific file needed. | |
#### Sidebar: CommonJS vs RequireJS/AMD | |
CommonJS has a more flexible module API that's an improvement over AMD. That is, you can manipulate the module and module.exports objects to provide access to load paths and other things. It also frees you from worrying about namespace conflicts. With CommonJS in browserify, your module names are just file names. Other module names used by your included packages are also file path names. | |
<!-- more end --> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment