A few people near me have heard the start of my rumblings about optimising the number of HTTP requests required for each page. There are a variety of reasons that you might want to do this, but that discussion is for another post. For now simply assume that I don't like unnecessary HTTP requests. Extrapolating from that you would reasonably assume that I really don't like wasted HTTP requests such as might happen when the url in a CSS @import directive 404's. If you assumed that, you'd be right.

I got fed up of tracking down the source of these errors in a few applications that I maintain so I fired up a TextMate session and scraped together this nasty little snippet of Ruby to do my dirty work for me.

#! /usr/bin/env ruby

css_root = File.expand_path(`pwd`.strip)
css_files = Dir[File.join(css_root, "**", "*.css")]

missing_imports = Hash.new([])
css_files.each_with_index do |css_file, index|
  imports = File.read(css_file).split(/\n|\r/).grep(/\@import url\((.*)\)/)
  imports.each do |import|
    desired_path = import.scan(/url\((["'\ ])?(.*)\1\)/).to_a.first.to_a.last
    desired_root = desired_path[0,1] == "/" ? css_root : File.dirname(css_file)
    filesystem_path = File.expand_path(File.join(desired_root, desired_path))
    if !File.exists?(filesystem_path)
      missing_imports[css_file] += [{ :path => filesystem_path, :directive => import }]

if missing_imports.any?
  puts "Missing files declared as imports in CSS:\n\n"

  missing_imports.keys.each do |origin|
    puts "Origin:               #{origin}"
    missing_imports[origin].each do |import|
      puts "Missing @import file: #{import[:path]}"
      puts "Directive:            #{import[:directive]}"
    puts ""
  puts "No imported files are missing. Well done."

Run it in the directory which serves your document root - for Rails applications this would be RAILS_ROOT/public/ - and it'll either spit out a list of missing files you've tried to @import or tell you that you've done well.

Missing files declared as imports in CSS:

Origin:               /Users/craig/projects/1.8/public/stylesheets/.../find_by_service.css
Missing @import file: /Users/craig/projects/1.8/public/stylesheets/.../a_to_z.css
Directive:            @import url('.../a_to_z.css');

Now, just to be clear, I don't like @import directives. I'd prefer they were completely removed from the CSS. They are popular with a lot of people though so I'll compromise for the moment: if you must use them, please make sure they're going to work.

written by
Disagree? Found a typo? Got a question?
If you'd like to have a conversation about this post, email craig@barkingiguana.com. I don't bite.
You can verify that I've written this post by following the verification instructions:
curl -LO http://barkingiguana.com/2008/11/03/make-sure-youre-importing-files-that-exist.html.orig
curl -LO http://barkingiguana.com/2008/11/03/make-sure-youre-importing-files-that-exist.html.orig.asc
gpg --verify make-sure-youre-importing-files-that-exist.html.orig{.asc,}