What have you found for these years?

2014-02-17

Rails + Bower on Heroku

Tested with Rails 3.2.15 and Bower 1.2.8.

First we need both Heroku's NodeJS and Ruby buildpacks,
using a multi-buildpack which could combine buildpacks.
Run this command to enable this multi-buildpack:

heroku config:add BUILDPACK_URL=https://github.com/ddollar/heroku-buildpack-multi.git

Then we need to create a .buildpacks file to
specify which buildpacks we want to use.

$ cat .buildpacks
https://github.com/heroku/heroku-buildpack-nodejs
https://github.com/heroku/heroku-buildpack-ruby

Next, we need a package.json for Heroku to
install npm dependencies, and run bower install.

$ cat package.json
{
  "name": "example",
  "version": "0.0.1",
  "repository": {
    "type": "git"
  },
  "dependencies": {
    "bower": "*"
  },
  "engines": {
    "node": "0.10.x"
  },
  "scripts": {
    "postinstall": "./node_modules/bower/bin/bower install"
  }
}

Note that repository is for silencing warnings from npm,
and scripts is where we specify how to run bower install.

Here's the bower.json to specify dependencies:
$ cat bower.json
{
  "name": "example",
  "version": "0.0.1",
  "dependencies": {
    "normalize-css": "*",
  },
}

We also need to specify the installation path for bower:
$ cat .bowerrc
{
  "directory": "app/assets/components"
}

We tried to install to this path because it seems Rails is
aware of this path, and people are using it. (Honestly, I don't
yet really understand what's Bower doing, just want to make it work)

Hopefully the last one, telling Rails to precompile assets from Bower.
We need to put this into our config/application.rb:
# Precompile assets from Bower
prefix = "#{Rails.root}/app/assets/components"
config.assets.precompile.push(*Dir["#{prefix}/*"].map{ |path|
  "#{path[/^#{Regexp.escape(prefix)}\/(.*)/, 1]}/*"
})

Updated 2014-08-12 00:04
This might work better:
config.assets.precompile = [lambda do |path|
  !path.start_with?('jquery/src') &&  # exclude broken jquery
    %w[.js .css .svg .png .jpg .gif .ttf .woff .eot .wav .mp3 .ogg].
      include?(File.extname(path)) && # compile only them
    Dir['app/assets/*'].find do |base|
      File.exist?("#{base}/#{path}")  # compile only from app/assets
    end
end]

I don't really understand why we need to do this, but I guess
this is how Rails designed, and I am too tired to argue with this.

That's basically everything we made Rails and Bower work on Heroku.

Example logs from Heroku:
-----> Fetching custom git buildpack... done
-----> Multipack app detected
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-nodejs
=====> Detected Framework: Node.js
-----> Requested node range:  0.10.x
-----> Resolved node version: 0.10.25
-----> Downloading and installing node
-----> Restoring node_modules directory from cache
-----> Pruning cached dependencies not specified in package.json
-----> Exporting config vars to environment
-----> Installing dependencies

       > example@0.0.1 postinstall /tmp/build_random-uuid
       > ./node_modules/bower/bin/bower install
[...]
-----> Caching node_modules directory for future builds
-----> Cleaning up node-gyp and npm artifacts
-----> Building runtime environment
=====> Downloading Buildpack: https://github.com/heroku/heroku-buildpack-ruby
=====> Detected Framework: Ruby
-----> Compiling Ruby/Rails
-----> Using Ruby version: ruby-2.1.0
-----> Installing dependencies using 1.5.2
       Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
[...]
       Your bundle is complete!
       Gems in the groups development and test were not installed.
       It was installed into ./vendor/bundle
       Bundle completed (1.29s)
       Cleaning up the bundler cache.
-----> Writing config/database.yml to read from DATABASE_URL
-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
[...]
-----> WARNINGS:
       Injecting plugin 'rails_log_stdout'
       Injecting plugin 'rails3_serve_static_assets'
       Add 'rails_12factor' gem to your Gemfile to skip plugin injection
       Using release configuration from last framework Ruby:
       ---
       addons:
       - heroku-postgresql:dev
       default_process_types:
         rake: bundle exec rake
         console: bundle exec rails console
         web: bundle exec rails server -p $PORT
         worker: bundle exec rake jobs:work
-----> Discovering process types
       Procfile declares types     -> web, worker
       Default types for Multipack -> console, rake

-----> Compressing... done, 12.93MB
-----> Launching... done, v1293
-----> Deploy hooks scheduled, check output in your logs
       http://example.herokuapp.com deployed to Heroku

To git@heroku.com:example.git
   fee1dead...deadbeef master -> master

0 retries:

Post a Comment

All texts are licensed under CC Attribution 3.0