heroku/heroku-buildpack-ruby — pull request #222 by pseudomuto (2014-02-02 17:50:59+00:00)
Title: Support for Node Modules via NPM Install

@hone and @schneems please review

# Problem

If you have a rails app that depends on node modules they won't be installed by this build package. There are workarounds, like using custom rake tasks, e.g.

```ruby
task :custom_task do
system("curl http://heroku-buildpack-nodejs.s3.amazonaws.com/nodejs-0.10.11.tgz -s -o - | tar xzf -")
Dir['./bin'].each { |script| system("chmod +x #{script}") }
system("node lib/node_modules/npm/bin/npm-cli.js install --force")
# your commands here...
end

task "assets:precompile" => :lineman_build
```

But this can get messy and is harder for people not so familiar with rake.

# Solution

This PR addresses the problem by downloading a (very) recent nodejs package from the heroku mirror of nodejs.org/dist (as used in the [node build pack](https://github.com/heroku/heroku-buildpack-nodejs)).

Once downloaded, the package is extracted and symlinks are created for the `node` and `npm` executables in the bin directory.

Finally, if _package.json_ exists in the root of the app, `npm install` will be run. To run a custom node task, simply add the script to your _package.json_ file, like so:

```javascript
{
"name": "my package name",
...
...
"scripts": {
"postinstall": "YOUR SCRIPT HERE..."
}
...
...
}
```

# Testing It All Out

## Create a Rails App

```
$ rails new sample_app
```

Add a package.json file

```javascript
{
"name": "sample_app",
"version": "0.1.0",
"repository": {
"type": "git",
"url": "[PUT ANY REPO HERE]"
},
"dependencies": {
"grunt-cli": "0.1.13",
"grunt-contrib-copy": "0.4.1"
},
"engines": {
"node": ">=0.10"
},
"scripts": {
"postinstall": "node_modules/.bin/grunt"
}
}
```

Add the Gruntfile.js file

```javascript
module.exports = function(grunt) {
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),

copy: {
main: {
src: 'package.json',
dest: 'copied_package.json'
}
}
});

grunt.loadNpmTasks('grunt-contrib-copy');
grunt.registerTask('default', ['copy']);
};

```

### Commit Your Changes

```
$ git init && git add .
$ git commit -m "Initial commit."
```

## Setup Heroku

```
$ heroku apps:create [NAME]
$ heroku config:set BUILDPACK_URL=https://github.com/pseudomuto/heroku-buildpack-ruby-lineman.git#run_npm_install_if_necessary
```

### Deploy

```
$ git push heroku master
```

### Verify

* You see the output from running `npm install`
* You see a notification the 1 files was copied