Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@brewster1134
Last active October 4, 2015 22:07
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brewster1134/2706526 to your computer and use it in GitHub Desktop.
Save brewster1134/2706526 to your computer and use it in GitHub Desktop.
sprockets-urlrewriter gem

After spending much time looking into the various solutions for serving vendored CSS containing relative urls (with much help from Bibliographic Wilderness, I decided on using the sprockets-urlrewriter preprocessor.

After some adjustments to the regex used to identify and rewrite the CSS urls, there was one other issue.

Although the sprockets-urlrewriter claims to rewrite relative urls to absolute ones, what it really does is rewrites urls relative to itself, to urls relative to the root asset directory.

This means that if the CSS all being compiled into application.css, everything works great. However if in development you are debugging your assets (a default in Rails), each CSS is linked individually. This means that the newly re-written urls are relative to application.css, but referenced in a different css file.

This is still ok if the location of the CSS files you are rewriting the urls for are located in a root asset path, but if they are nested, your new urls dont work anymore.

For example, take the following directory structure of some 3rd party asset you want to include in the pipeline

/vendor
|_/assets
  |_/stylesheets
    |_/folder_one
      |_/css
      | |_default.css
      |     .{ background: url(../img/image.png); }
      |_/img
        |_image.png

Before urlrewriter with only the asset pipeline, in development we would get this...

/assets/folder_one/default.css
  .{ background: url(../img/image.png); }

Works great! The image url is still relative to the original file it is in. But in production not so much...

/assets/application.css
  .{ background: url(../img/image.png); }

This is exactly what the urlrewriter is for! Register urlrewriter, and now everything in productions is working.

/assets/application.css
  .{ background: url(folder_one/img/image.png); }
/assets/folder_one/image.png

All the css assets are now all within /assets/application.css. Since the new url is also relative to /assets, the image path is fine. But what happened in development?

/assets/folder_one/default.css
  .{ background: url(folder_one/img/image.png); }

Because we want to debug each asset, the rewritten url intended for the root asset path, is now relative to a directory the css file does not live in.

Since the preprocessor is unaware of the rails environment it is rewriting for, we need to restrict when to preprocess.

The solution I decided on was restricting the preprocessor from being registered if the css assets are not compiled into a single application.css.

Rails.application.assets.register_preprocessor 'text/css', Sprockets::UrlRewriter unless Rails.application.config.assets.debug

@hershmire
Copy link

Good stuff. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment