How to setup Bower within Rails
28 Dec 2013After arguing for a Bower/Rails integration in Why Rails needs Bower, I want to show how Bower can be integrated within Rails.
The objective is for all JS/CSS tooling and libraries to be managed by Bower while still holding to a standard Rails MVC. In other words, we’ll still use Rails to render the view templates rather than moving to a Rails-API/Javascript templated frontend. All we’re doing is using Bower to govern the CSS and JS dependencies.
1. Create a new Rails and Controller/View
Create a new Rails app with a controller and view to test that JS/CSS files are properly included.
rails new simple
cd simple
rails generate controller home index
Add this in simple/app/views/home/index.html.erb
view to test that Bootstrap is properly setup.
<h1>Hello, <span class="glyphicon glyphicon-globe"></span> !</h1>
2. Setup Bower
Install node if you haven’t already. Joynet has great NodeJS install instructions.
Use NPM to setup package.json
.
npm init
Install Bower, save as a development dependency. I chose to ignore the node_modules
directory, but you can decide that for yourself.
npm install --save-dev bower
User bower to setup the bower.json
.
bower init
By default, Bower installs packages into simple/app/bower_components
. In my opinion, it simplifies the codebase to install Bower components in the root directory, simple/bower_modules
. We’ll have Bower install components there by adding a .bowerrc
file.
{
"directory": "bower_components"
}
Instruct Bower to to install jQuery
, jquery-ujs
, and bootstrap
.
bower install --save jquery jquery-ujs bootstrap
Looking in simple/bower_components
reveals that Bower installed all of jquery’s project into simple/bower_components
. This is a problem. All we need and want is the jquery.js
file.
3. Use bower-install
to copy files into vendor/assets
We can use bower-installer to copy specific files from simple/bower_components
into the simple/vendor/assets
folder for them to be included during the Rails’ AssetPipeline compilation process.
Install bower-installer
and save as development dependency,
npm install --save-dev bower-installer
Modify the bower.json
according to bower-installer
README telling bower-installer
to install the js, css, and random font files into the vendor assets directory. Since Rails by default does not pickup the vendor/assets/fonts
directory, we’ll add this to the Rails asset path too.
// =========== bower.json
"test",
"tests"
],
+ "install": {
+ "path": {
+ "css": "vendor/assets/stylesheets",
+ "js": "vendor/assets/javascripts",
+ "eot": "vendor/assets/fonts",
+ "svg": "vendor/assets/fonts",
+ "ttf": "vendor/assets/fonts",
+ "woff": "vendor/assets/fonts"
+ }
+ },
"dependencies": {
"jquery": "~2.0.3",
"jquery-ujs": "*",
# ======== application.rb
module Simple
class Application < Rails::Application
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
+
+ config.assets.paths << Rails.root.join('vendor', 'assets', 'fonts')
end
end
Run bower-installer. You should see the asset source files appear in the vendor folders.
bower-installer
4. Modify Gemfile and application.js files
Remove jquery-rails and jquery-ujs from the Gemfile. Run bundle install
.
Modify the application.js
and application.css
files to reflect changes and bootstrap inclusion. Notice that the javascript file associated with jquery-ujs
is actually named rails.js
.
// ========== application.js
//= require jquery
-//= require jquery_ujs
+//= require rails
//= require turbolinks
+//= require bootstrap
//= require_tree .
// ========== application.css
*
*= require_self
+ *= require bootstrap
*= require_tree .
*/
5. Test this out.
Boot up rails and test this up by going to, localhost:3000/home/index.
We have an issue. The Bootstrap font-face is not coming through since we do not see a world image. And if you look in the Javascript console, you’re see the we have 3 HTTP 404s. Why? Bootstrap v3.0.3 bootstrap.css#LL2356
expects fonts to be available at ../fonts
but Rails makes this available at /assets
. :disappointed:
6. Fix the font-face issue.
My solution resolves the HTTP 404s, but I’m content nor happy with it. I’d love to hear how others have conquered this issue and update this post with a better solution. Here’s what I’m doing to fix the HTTP 404s.
Add @font-face
declaration in the application.css file and substitute ../fonts
for /assets
since this is how the Rails Asset Pipeline makes them available.
// ========== application.css
+
+ @font-face {
+ font-family: 'Glyphicons Halflings';
+ src: url('/assets/glyphicons-halflings-regular.eot');
+ src: url('/assets/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'),
+ url('/assets/glyphicons-halflings-regular.woff') format('woff'),
+ url('/assets/glyphicons-halflings-regular.ttf') format('truetype'),
+ url('/assets/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
+}
Remove the @font-face
declaration from the bootstrap.css
file in vendor/assets/stylesheets
.
// ========== bootstrap.css
-@font-face {
- font-family: 'Glyphicons Halflings';
- src: url('../fonts/glyphicons-halflings-regular.eot');
- src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons-halflingsregular') format('svg');
-}
-
This will stop the HTTP 404s during page loads, but I find this unsatisfactory because bower-installer
will copy over the original bootstrap.css
file every time it’s run. I still advocate for this since it stops the HTTP 404s. I believe HTTP 404s should never, never show up in production.
Please provide feedback
I’m hopeful that we embrace better tools to holistically manage frontend dependencies so we focus on creating beautiful UIs.