Speed up Drupal web-site by reducing HTTP requests using data URI schemes

12 Dec 2009
Posted by doq

Recently we have discussed Data URI schemes previously and were trying to develop a patch for Drupal 6 that will create optimized CSS automatically. The latter solution break IE 6/7 and probably other browsers that do not support data URI schemes. Today I have a better patch that just provides a workaround for IE 6/7 (yes, these browsers won't gain any performance improvement using this patch).

Here is the patch, comments are added making it self-descriptive. Please test it on your environment and provide feedback:

--- includes/common.inc.orig	2009-09-16 22:34:14.000000000 +0300
+++ includes/common.inc	2009-12-12 18:06:04.000000000 +0200
@@ -1923,9 +1923,11 @@
           $contents = drupal_load_stylesheet($file, TRUE);
           // Return the path to where this CSS file originated from.
           $base = base_path() . dirname($file) .'/';
+          _drupal_build_css_element(NULL, $base);
           _drupal_build_css_path(NULL, $base);
+          _drupal_build_css_data_uri(NULL, $base);
           // Prefix all paths within this CSS file, ignoring external and absolute paths.
-          $data .= preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $contents);
+          $data .= preg_replace_callback('/[^}]+{[^{}]+(url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\))[^{}]*}/i', '_drupal_build_css_element', $contents);
         }
       }
     }
@@ -1936,13 +1938,33 @@
     preg_match_all($regexp, $data, $matches);
     $data = preg_replace($regexp, '', $data);
     $data = implode('', $matches[0]) . $data;
-
     // Create the CSS file.
     file_save_data($data, $csspath .'/'. $filename, FILE_EXISTS_REPLACE);
   }
   return $csspath .'/'. $filename;
 }
 
+function _drupal_build_css_element($matches, $base = NULL) {
+  static $_base;
+  // Store base path for preg_replace_callback.
+  if (isset($base)) {
+    $_base = $base;
+    return;
+  }
+
+  $data_uri = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_data_uri', $matches[0]);
+
+  $matches[0] = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $matches[0]);
+
+ // Support IE6.
+  $ie6 = '* html '. $matches[0];
+
+  // Support IE7.
+  $ie7 = '*+html '. $matches[0];
+
+  return $data_uri . $ie6 . $ie7;
+}
+
 /**
  * Helper function for drupal_build_css_cache().
  *
@@ -1953,6 +1975,7 @@
   // Store base path for preg_replace_callback.
   if (isset($base)) {
     $_base = $base;
+    return;
   }
 
   // Prefix with base and remove '../' segments where possible.
@@ -1962,10 +1985,54 @@
     $last = $path;
     $path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path);
   }
+
   return 'url('. $path .')';
 }
 
 /**
+ * Helper function for drupal_build_css_cache().
+ *
+ * This function will prefix all paths within a CSS file.
+ */
+function _drupal_build_css_data_uri($matches, $base = NULL) {
+  static $_base;
+  // Store base path for preg_replace_callback.
+  if (isset($base)) {
+    $_base = $base;
+    return;
+  }
+
+  // Prefix with base and remove '../' segments where possible.
+  $path = $_base . $matches[1];
+
+  $path2 = substr($path, strlen(base_path()));
+  // Embed images that are less then 1K in size.
+  if ($image = image_get_info($path2)) {
+    if ($image['file_size'] < 1024) {
+      $path = data_uri_scheme($path2, $image['mime_type']);
+    }
+  }
+
+  return 'url('. $path .')';
+}
+
+/**
+ * Generate data URI scheme to be used inside url() attribute.
+ *
+ * @param $file
+ *   File path to generate data URI scheme from.
+ * @param $mime
+ *   MIME type of file, e.g. image/png, image/gif.
+ * @return
+ *   Data URI scheme to be used inside url() attribute.
+ */
+function data_uri_scheme($file, $mime) {
+  $contents = file_get_contents($file);
+  $base64 = base64_encode($contents);
+  return 'data:'. $mime .';base64,'. $base64;
+}
+
+/**
  * Loads the stylesheet and resolves all @import commands.
  *
  * Loads a stylesheet and replaces @import commands with the contents of the

Results

Results should be the same as in previous article, please refer to them.

AttachmentSize
D6-data_uri_schemes-2.patch3.46 KB

Comments

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

 
 
 
If you have found mistakes in the text then please select it and press Ctrl-Enter to send report to the site administrator.