Drupal 7 includes a big re-factor of the way CSS and Javascript are aggregated. What does this mean for your sites? In short:
- You will see a greater number of files compared to D6 - this is normal and not usually cause for alarm. Surprisingly, more files is sometimes better.
- To ensure efficient aggregation, the most important thing developers can do is choose the parameters to
drupal_add_css
and drupal_add_js
carefully. And if you encounter contrib modules that are using the wrong parameters, please file patches!
This was a somewhat controversial change, and understanding the new strategy (and how to override it) requires going a bit deeper.
Previously, all files were merged together into one giant file (at least within the same scope or media type). This strategy worked well on simple sites with few or no contrib modules. Unfortunately, many contrib modules in D6 incorrectly add conditional* CSS and Javascript files – resulting in changing aggregates as you browse from page to page. If even a few lines of code differ, the entire aggregate (including large libraries like jQuery and jQuery UI) must be re-downloaded, consuming extra bandwidth.
* "Conditional" files in this context refers to files that are added to some pages but not others - an example would be calling drupal_add_css()
in a theme function. In D6 such calls should have the $preprocess
value set to FALSE
to prevent splitting the aggregate.
The D7 way
D7 uses a new strategy to address this - aggregates are split into three groups:
CSS_SYSTEM
, CSS_DEFAULT
, and CSS_THEME
for styles, and JS_LIBRARY
, JS_DEFAULT
, and JS_THEME
for Javascript. Each group is further subdivided into files that load on every page, and files that load conditionally based on the 'every_page'
option. Note this option has some potential for confusion - it doesn't cause the file to be loaded on every page - it's merely a "hint" to the core system to place it in that group.
Ultimately, the intent of these divisions is to group files into functional groups that are smaller and less likely to be split by an errant conditional style or script. We get separate files for core libraries, the theme, and page-specific files. Looking at the results, a stock Drupal 7 outputs eight stylesheets (including browser styles), while D6 only has three in the default install. Is this optimal? The answer will be different for each site.
Custom tuning
D7 adds two new hooks that allow you to alter styles and scripts before they are rendered:
hook_css_alter()
hook_js_alter()
At least one contrib project taking advantage of this functionality has already been created: Core Library. I haven't had a chance to test it yet, but the module's intent is to optimize the groupings by "learning" as visitors browse your site.
One thing to note if you decide to undertake customizing these groupings: In Drupal 7.0, the insertion order of styles and scripts is always preserved, even at the expense of sometimes splitting a group. A patch has been submitted that proposes relaxing this a bit.
Back to D6
If the previous Drupal 6 strategy is a better match for your site, you can drupal_alter
your way back with this code in a custom module:
/**
* Implements hook_js_alter().
*/
function mymodule_js_alter(&$javascript) {
uasort($javascript, 'drupal_sort_css_js');
$i = 0;
foreach ($javascript as $name => $script) {
$javascript[$name]['weight'] = $i++;
$javascript[$name]['group'] = JS_DEFAULT;
$javascript[$name]['every_page'] = FALSE;
}
}
/**
* Implements hook_css_alter().
*/
function mymodule_css_alter(&$css) {
uasort($css, 'drupal_sort_css_js');
$i = 0;
foreach ($css as $name => $style) {
$css[$name]['weight'] = $i++;
$css[$name]['group'] = CSS_DEFAULT;
$css[$name]['every_page'] = FALSE;
}
}