Last Updated: September 09, 2019
·
15.49K
· royletron

Bower and Rails. Friends forever.

Picture

Bower is an uber-trendy package manager supplying a huge range of Javascript and CSS frameworks and plugins, which runs via Node. I find it really useful when prototyping because I can just burn through any number of things until I find exactly what I am looking for, and recently I thought "How could I use that with the Rails pipeline". Thankfully the answer is quite simple, but, as with most things, there are levels of integration, starting with the simple (but less efficient), going to more complicated, I will cover my preferred method.

The first thing to do is to ensure you have everything set up that you need, so get Node and NPM setup (Google is your friend) and then install Bower:

npm install -g bower

Next you need get Bower to play nicely with the Rails directory structure. To do that you have to modify Bowers main configuration file .bowerrc which needs to be in your user folder (it doesn't exist by default). Make it look like this

{
  "directory": "app/assets/components"
}

You can set it up to where you feel suits your way of working, like the vendor folder for example, but I find it easiest in a specified folder within assets. The next step is to define what you want Bower to install into your project, so start off by looking up what you need in the component list and then you can build your bower.json file, which will sit in your project root

{
  "name": "my-project",
    "dependencies": {
    "underscore": "~1.4.4"
  }
}

You can add whatever packages you want at this point, you can also use the Bower command line tools to search for packages:

bower search moment

Which will return results like this

Search results:

moment git://github.com/timrwood/moment.git
momentjs git://github.com/moment/moment
angular-moment git://github.com/urish/angular-moment.git
momentjs-web-lang git://github.com/vperron/momentjs-web-lang.git
moment-range git://github.com/gf3/moment-range.git
moment-timezone git://github.com/moment/moment-timezone.git
angular-momentum-scroll git://github.com/wzr1337/bower-angular-momentum-scroll.git
momentum-css git://github.com/edgincvg/momentum-css.git
moment-jalaali git://github.com/behrang/moment-jalaali.git
moment-fromNowUpdate git://github.com/garethadavies/moment.fromNowUpdate.git

You can then install the package

bower install moment --save

Adding the save parameter ensures that Bower adds the dependancy to your bower.json file. You can leave this out if you just want to try things out, and then you can add them to your dependancy file yourself later. You can also uninstall packages

bower uninstall moment

You also would also have to remove it from your bower.json file as well.

The final step is to get Rails to work nicely with your Bower components directory, as well as including them within the relevant CSS and JS files. Starting with getting Rails to add it to the asset pipeline, you will need to modify the application.rb file in the /config/ dir, and add the following within the *'Application' class:

// ...
config.assets.paths << Rails.root.join('app', 'assets', 'components')
// ...

Make sure you modify this if not using the components folder.

Then it is just a case of calling the packages into your main asset code, for Javascript files it is as simple as adding

//= require underscore/underscore-min

For the Bower component you want to add, where it is just the path relative to the components directory and then the JS file within it. And for CSS (SASS in this case):

@import "normalize-css/normalize";

Again where the path is relative to the components directory.

9 Responses
Add your response

DO NOT USE app/assets/ FOR EXTERNAL ASSETS.

For this you have vendor/assets. Next thing is that then you do not need to place all your assets in extra folder.

over 1 year ago ·

@hauleth is there a reason NOT to use this folder?

Personally I find having it outside of the Rails world better as it is less likely to conflict. Also it gives us a higher level of control when it comes to ignoring the main vendors folder for Git and leave the Bower assets within Git as you are less likely to find a Rails dev who is clued up with Bower.

I do say that you should use the folder that works for you....

over 1 year ago ·

@royletron, yes convention.You should keep some organisation in your code. For me app/ folder is only for my application code, not for any library.

Also I don't keep any of Bower installed libs in Git repo. All of them are downloaded on server before assets:precompile to keep application repository with only my app code. IMHO it is the best options. If you wan't store external libs in your Git tree then you should think about using Git submodules instead of Bower.

over 1 year ago ·

@hauleth I would argue that actually the convention proves that app/assets is the right place, as Bower doesn't really strictly fit into the Rails asset pipeline, and you could suggest that because of that it counts as application assets... Anyhoo, each to their own devices, for our teams needs this solution works as our front end staff like Bower and some of the elder Rails heads don't want to touch it (and equally don't want it touching their areas). When it comes to prototyping this provides us with the right flexibility, which was the initial intention of the piece.

I would stress to anyone that has got this far in reading the comments to ensure that they don't take any instruction as gospel and find how to make it work for their specific needs!

over 1 year ago ·

Also worth adding that you can easily set up as @hauleth suggests with rake tasks to really get Bower fully integrated into Rails with this gem. Which funnily defaults to the vendor folder (but allows you to override it to wherever if required).

over 1 year ago ·

@hauleth

There's quite a lot of debate in the nodejs community about whether or not to checkin dependencies, with the 'check'em in' side in the lead at the moment. See http://addyosmani.com/blog/checking-in-front-end-dependencies/ for more.

I have found git submodules to be a dismal alternative to proper package managers like bower, npm or rubygems.

over 1 year ago ·

@royletron

but allows you to override it to wherever if required

Not really "wherever": wherever inside "lib" or "vendor" directory (according to the Rails convention)

over 1 year ago ·

Rails 3.x

There is a very LARGE issue with this approach. Sprockets itself is over bearing when it comes to actually finding js and css files... It doesn't check the actual file extension.

Example:
Sprockets::EncodingError: /vagrant/vendor/assets/bower_components/angular/angular.min.js.gzip

There are a lot of articles on Bower integration in Sprockets, and really, it seems like they're all a rehash with a few opinions on top. But as soon as you add Angular, an extremely popular library, it breaks the standard asset pipeline.

So there should be some cautionary advice around this.

over 1 year ago ·

No one else mentioned that you need to pass --save to the bower command in order for it to be written to bower.json. Thanks for that! :D

over 1 year ago ·