2 ----------------------------------
3 ADVANCED CSS/JS AGGREGATION MODULE
4 ----------------------------------
14 * JavaScript Bookmarklet
15 * Technical Details & Hooks
16 * Single htaccess rules
23 Assuming that this guide was followed:
24 http://2bits.com/drupal-planet/reducing-server-resource-utilization-busy-sites-implementing-fast-404s-drupal.html
25 and your having issues with Advanced CSS/JS Aggregation. Advagg works similar
26 to imagecache, thus we need to add in an exceptions for the directories that
27 advagg uses. Replace this if statement
29 if (!strpos($_SERVER['QUERY_STRING'], 'imagecache')) {
33 if (!strpos($_SERVER['QUERY_STRING'], 'imagecache') && !strpos($_SERVER['QUERY_STRING'], '/advagg_')) {
35 This will most likely be in your settings.php file.
37 If using Nginx make sure there is a rule similar to this in your configuration.
38 http://drupal.org/node/1116618#comment-4321724
40 If this is still an issue you can try setting the
41 "IP Address to send all asynchronous requests to" setting on the
42 admin/settings/advagg/config page to -1. This will use the hostname instead of
43 an IP address when making the http request.
45 If you are still having problems, open an issue on the advagg issue queue:
46 http://drupal.org/project/issues/advagg
52 Advanced CSS/JS Aggregation Core Module:
53 * Imagecache style CSS/JS Aggregation. If the file doesn't exist it will be
55 * Stampede protection for CSS and JS aggregation. Uses locking so multiple
56 requests for the same thing will result in only one thread doing the work.
57 * Zero file I/O if the Aggregated file already exists. Results in better page
58 generation performance.
59 * Fully cached CSS/JS assets making this module faster than drupal core.
60 * Smarter aggregate deletion. CSS/JS aggregates only get removed from the cache
61 if they have not been used/accessed in the last 3 days.
62 * Smarter cache flushing. Scans all CSS/JS files that have been added to any
63 aggregate; if that file has changed then rebuild all aggregates that contain
64 the updated file and give the newly aggregated file a new name. The new name
65 ensures changes go out when using CDNs.
66 * Works with Drupal's private file system. Can Use a separate directory for
67 serving aggregated files from.
68 * Footer JS gets aggregated as well.
69 * One can add JS to any region & have it aggregated.
70 drupal_add_js($data, 'module', 'left') is now possible; JS is appended to the
71 the end of that region.
72 * One can add external JS/CSS resources.
73 drupal_add_js('http://example.org/example.js', 'external');
74 drupal_add_css('http://example.org/example.css', 'external');
76 * Url query string to turn off aggregation for that request. ?advagg=0 will
77 turn off file aggregation if the user has the "bypass advanced aggregation"
78 permission. ?advagg=-1 will completely bypass all of Advanced CSS/JS
79 Aggregations modules and submodules.
80 * Button on the admin page for dropping a cookie that will turn off file
81 aggregation. Useful for theme development.
82 * Url query string to turn on advagg debugging for that request.
83 ?advagg-debug=1 will output a large debug string to the watchdog if the user
84 has the "bypass advanced aggregation" permission.
85 * Gzip support. All aggregated files can be pre-compressed into a .gz file and
86 served from Apache. This is faster then gzipping the file on each request.
87 * IE Unlimited CSS support. If using ?advagg=0 the CSS output will change
88 to use @import style in order to get around the 31 CSS files limit in IE.
89 * CDN support. Advagg integrates with this module.
90 * jQuery Update support. Advagg integrates with this module.
91 * LABjs support. Advagg integrates with this module.
92 * One year browser cache lifetimes for all aggregated files. This is a good
94 * Drush support. "cc advagg" will issue a smart cache flush.
95 * Admin menu support. Cache flushing Advanced CSS/JS Aggregation is available
96 in the "Flush all caches" menu.
98 Advanced CSS/JS Aggregation Submodules:
100 * CSSTidy library support. Can compress the generated CSS files with the
102 * CSS Compressor 3.0 support. https://github.com/codenothing/css-compressor
104 * JSMin+ library support. Can compress the generated JS files with the jsmin+
106 * JSMin PHP Extension support. http://www.ypass.net/software/php_jsmin/
107 * Use Dean Edwards Packer on non gzipped files. .gz files will not be packed.
109 * Google's CDN network. Load jquery.js & jquery-ui.js from using the Google
110 Libraries API. This is a good thing.
112 * Bundler. Will split up an aggregate into sub aggregates for better load
113 times throughout your site.
117 * Parallel CSS - AdvAgg Plugin. Have url()'s in css files reference different
124 Settings page is located at:
125 admin/settings/advagg
126 * Enable Advanced Aggregation. You can disable the module here. Same effect as
127 placing ?advagg=-1 in the URL.
128 * Use AdvAgg in closure. If enabled javascript files in the closure region will
129 be aggregated by advagg.
130 * Generate CSS/JS files on request (async mode). If advagg doesn't have a route
131 back to its self and this is enabled then you will have a broken site. With
132 this enabled one can expect much quicker page generation times after a cache
134 * Gzip CSS/JS files. For every Aggregated file generated, this will create a
135 gzip version of that and then serve that out if the browser accepts gzip
137 * Generate .htaccess files in the advagg_* dirs. If your using the rules
138 located at the bottom of this document in your webroots htaccess file then
139 you can disable this checkbox.
140 * Regenerate flushed bundles in the cache flush request. You can enable if your
141 server will not timeout on a request. This will call advagg_rebuild_bundle()
142 as a shutdown function for every bundle that has been marked as expired;
143 thus rebuilding that bundle in the same request as the flush.
144 * Use a different directory for storing advagg files. Only available if your
145 using a private file system. Allows you to save the generated aggregated
146 files in a different directory. This gets around the private file system
147 restrictions. If boost is installed, you can safely use the cache directory.
148 * Aggregation Inclusion Mode. Should the page wait for the aggregate to be
149 built before including the file, or should it send out the page with
150 aggregates not included.
151 * Disable page caching if all aggregates are not included on the page.
152 * File Checksum Mode. mtime is the file modification time. md5 is a hash of the
154 * IP Address to send all asynchronous requests to. If you wish to have one
155 server generate all CSS/JS aggregated files then this allows for that to
157 * Smart cache flush button. Scan all files referenced in aggregated files. If any of
158 them have changed, increment the counters containing that file and rebuild
160 * Cache Rebuild button. Recreate all aggregated files. Useful if JS or CSS
161 compression was just enabled.
162 * Forced Cache Rebuild. Recreate all aggregated files by incrementing internal
163 counter for every bundle. One should never have to use this option.
164 * Master Reset. Clean slate; same affect as uninstalling the module.
165 * Rebuild htaccess files. Recreate the generated htaccess files.
166 * Aggregation Bypass Cookie. This will set or remove a cookie that disables
167 aggregation for the remainder of the browser session. It acts almost the same
168 as adding ?advagg=0 to every URL.
170 Additional information is available at:
171 admin/settings/advagg/info
172 * Hook Theme Info. Displays the preprocess_page order. Used for debugging.
173 * CSS files. Displays how often a files checksum has changed and any data
175 * JS files. Displays how often a files checksum has changed and any data
177 * Modules implementing advagg hooks. Lets you know what modules are using
179 * Missing files. Lets you know the files that are trying to be added but are
181 * Asynchronous debug info. Outputs the the full object returned from
182 drupal_http_request() which is helpful when debugging async issues.
188 --Bundler Sub Module--
189 When using the bundler sub module, tools like Google Page Speed and YSlow will
190 complain that not all CSS/JS files are in one aggregate. This has to do with
191 how drupal_add_js/drupal_add_css works. You can get a better score on these
192 tools by placing all files into one aggregate, but the issue with doing that
193 is, different pages load different css/js files, thus on page 2 of the users
194 visit, you will get worse performance because the browser has to re-download a
195 whole new css & js aggregate rather then the smaller aggregate that only
196 changed. The bundler attempts to work around this issue by creating various
197 bundles, each one being chosen fairly smartly so that instead of downloading a
198 200KB js file you only have to download a 20KB file on the 2nd page.
200 The bundler sub module is all about balancing trade offs. You can make a site
201 that had really good performance stats according to the tools but you would
202 then have to re-download just about everything on a different page of your
203 site, because not all your pages are the same. If you don't care about this and
204 want a good score from pagespeed, disable the bundler sub-module. That will
205 give you a better score, but then you have to download a new (large) aggregate
206 on different parts of your website and already downloaded file reuse will be
210 The cron job for AdvAgg is there as a garbage collector. It only needs to run
211 once a week; running it every hour isn't going to be bad, it isn't necessary
215 JAVASCRIPT BOOKMARKLET
216 ----------------------
218 You can use this JS code as a bookmarklet for toggling the AdvAgg URL parameter.
219 See http://en.wikipedia.org/wiki/Bookmarklet for more details.
221 javascript:(function(){var loc = document.location.href,qs = document.location.search,regex_off = /\&?advagg=-1/,goto = loc;if(qs.match(regex_off)) {goto = loc.replace(regex_off, '');} else {qs = qs ? qs + '&advagg=-1' : '?advagg=-1';goto = document.location.pathname + qs;}window.location = goto;})();
224 TECHNICAL DETAILS & HOOKS
225 -------------------------
228 * There are two database tables and two cache table used by advagg.
229 * Files are generated by this pattern: css_[MD5]_[Counter].css
230 * Every JS file is tested for compressibility. This is necessary because jsmin+
231 can run out of memory on certain files. This allows us to catch these bad
232 files and mark them. Also allows us to skip files that are already
236 * hook_advagg_css_alter. Modify the data before it gets written to the file.
237 Useful for compression.
238 * hook_advagg_css_inline_alter. Modify the data before it gets embedded in the
239 page. Useful for compression.
240 * hook_advagg_css_pre_alter. Modify the raw $variables['css'] before it gets
241 processed. Useful for file replacement.
242 * hook_advagg_css_extra_alter. Allows one to set the a prefix and suffix to be
243 added into the HTML DOM. Useful for CSS conditionals.
245 * hook_advagg_js_alter. Modify the data before it gets written to the file.
246 Useful for compression.
247 * hook_advagg_js_inline_alter. Modify the data before it gets embedded in the
248 page. Useful for compression.
249 * hook_advagg_js_pre_alter. Modify the raw $javascript before it gets
250 processed. Useful for file replacement.
251 * hook_advagg_js_extra_alter. Allows one to set the a prefix and suffix to be
252 added into the HTML DOM.
253 * hook_advagg_js_header_footer_alter. Allows one to move JS from the header to
254 the footer. Also one can look at both header and footer JS arrays before they
257 * hook_advagg_filenames_alter. Allows for a one to many relationship. A single
258 request for a bundle name can result in multiple bundles being returned.
259 * hook_advagg_files_table. Allows for modules to mark a file as expired.
260 * advagg_master_reset. Allows other modules to take part in a master reset.
261 * advagg_disable_processor. Allows one to turn off advagg from a hook. See the
262 advagg_advagg_disable_processor() function for example usage.
263 * advagg_disable_page_cache. Allows 3rd party page cache plugins like boost or
264 varnish to not cache this page.
265 * advagg_bundler_analysis_alter. Give installed modules a chance to alter the
266 bundler's analysis array.
268 JS/CSS Theme Override:
270 $conf['advagg_css_render_function'] - advagg_unlimited_css_builder
271 $conf['advagg_js_render_function'] - advagg_js_builder
273 JS/CSS File Save Override:
275 $conf['advagg_file_save_function'] - advagg_file_saver
278 * advagg_add_css_inline. Adds the ability to add in inline CSS to the page with
279 a prefix and suffix being set as well.
282 SINGLE HTACCESS RULES
283 ---------------------
285 If the directory level htaccess rules are interfering with your server, you can
286 place these rules in the Drupal root htaccess file. Place these rules after
287 "RewriteRule ^(.*)$ index.php?q=$1 [L,QSA]" but before "</IfModule>"
290 # Rules to correctly serve gzip compressed CSS and JS files.
291 # Requires both mod_rewrite and mod_headers to be enabled.
292 <IfModule mod_headers.c>
293 # Serve gzip compressed CSS/JS files if they exist and client accepts gzip.
294 RewriteCond %{HTTP:Accept-encoding} gzip
295 RewriteCond %{REQUEST_URI} (^/(.+)/advagg_(j|cs)s/(.+)\.(j|cs)s) [NC]
296 RewriteCond %{REQUEST_FILENAME}\.gz -s
297 RewriteRule ^(.*)\.(j|cs)s$ $1\.$2s\.gz [QSA]
299 # Serve correct content types, and prevent mod_deflate double gzip.
300 RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1]
301 RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1]
303 <FilesMatch "\.(j|cs)s\.gz$">
304 # Serve correct encoding type.
305 Header set Content-Encoding gzip
306 # Force proxies to cache gzipped & non-gzipped css/js files separately.
307 Header append Vary Accept-Encoding
312 You also need to place these rules at the very end of your htaccess file, after
316 # AdvAgg Rules Start.
317 <FilesMatch "^(j|cs)s_[0-9a-f]{32}_.+\.(j|cs)s(\.gz)?">
319 <IfModule !mod_headers.c>
321 <IfModule !mod_expires.c>
326 # Use Expires Directive.
327 <IfModule mod_expires.c>
330 # Enable expirations.
332 # Cache all aggregated CSS/JS files for 480 weeks after access (A).
333 ExpiresDefault A290304000
337 <IfModule mod_headers.c>
338 # Set a far future Cache-Control header to 480 weeks.
339 Header set Cache-Control "max-age=290304000, no-transform, public"
340 # Set a far future Expires header.
341 Header set Expires "Tue, 20 Jan 2037 04:20:42 GMT"
342 # Pretend the file was last modified a long time ago in the past.
343 Header set Last-Modified "Wed, 20 Jan 1988 04:20:42 GMT"
344 # Do not use etags for cache validation.
351 Be sure to disable the "Generate .htaccess files in the advagg_* dirs" setting
352 on the admin/settings/advagg page after placing these rules in the webroots
353 htaccess file. This is located at the same directory level as Drupal's
360 http://drupal.org/node/1116618
363 ### advagg_css and advagg_js support
365 location ~* files/advagg_(?:css|js)/ {
369 add_header Cache-Control "max-age=290304000, no-transform, public";
370 add_header Last-Modified "Wed, 20 Jan 1988 04:20:42 GMT";
371 try_files $uri @drupal;