Bower and Rails. Friends forever.
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.
Written by Darren
Related protips
9 Responses
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.
@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....
@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.
@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!
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.
but allows you to override it to wherever if required
Not really "wherever": wherever inside "lib" or "vendor" directory (according to the Rails convention)
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.
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