Concrete5 and Minify: Combine, minify and cache JS and CSS to speed up page loads

Permalink 2 users found helpful
I have taken the ideas from another thread (http://www.concrete5.org/community/forums/customizing_c5/concrete5-on-steroids-take-two/) and came up with another solution. Taking a look through libraries/view.php I found some commented out code to use Minify (http://code.google.com/p/minify/). I ran with this idea and modified a few other files to do the following:

- config/site.php option to turn it on or off
- By default include CSS in the header and JS in the footer, with an override
- Load jquery from Google's CDN in the header for the public
- Only include ccm.base.css and ccm.base.js when the user is logged in (if you use the layouts feature you need to change something, see below)
- Use the OP's method to compress the page, but hoping for the tinifier optimizer

To get it to work, you need to download minify, install it at the root of your site (I'm still testing to see if it can live in /tools/ for example, but the docs say SITE_ROOT) and edit the /min/config.php to point to concrete5's cache directory:

$min_cachePath = $_SERVER['DOCUMENT_ROOT'] . '/files/cache';


Also, if you have more than 10 CSS or JS files in the same directory, you need to up the file limit:

$min_serveOptions['minApp']['maxFiles'] = 20;


Ensure your theme has this code as close to the closing body tag as possible:
<?php   Loader::element('footer_required'); ?>


Include your template-specific CSS/JS before header_required like so:

<?php
   $html = Loader::helper('html');
   $this->addHeaderItem($html->css(array('url' => 'css/theme.css'))); // CSS in header by default
   $this->addHeaderItem($html->css(array('url' => 'css/footer.css', 'header' => '0'))); // CSS in footer
   $this->addHeaderItem($html->javascript(array('url' => 'js/footer.js'))); // JS in footer by default
   $this->addHeaderItem($html->javascript(array('url' => 'js/header.js', 'header' => '1'))); // JS in header
   Loader::element('header_required');
?>


Edit elements/header_required.php to include site-specific CSS and JS. If your site does not use jQuery, you can get rid of it here too.

If you use the layouts feature, make sure ccm.base.css and ccm.base.js is included for everyone. Edit elements/header_required.php:

if ($u->isRegistered()) {
   $this->addHeaderItem($html->javascript(array('url' => 'jquery.js', 'header' => '1')), 'CORE');
} else {
   $this->addHeaderItem($html->javascript(array('url' => 'http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js'), 'header' => '1')),   'CORE');
}
// add site specific /css and /js here
$this->addHeaderItem($html->css(array('url' => 'ccm.base.css')), 'CORE');
$this->addHeaderItem($html->javascript(array('url' => 'ccm.base.js', 'header' => '1')), 'CORE');
//$this->addHeaderItem($html->javascript(array('url' => 'plugins.js' )));
//$this->addHeaderItem($html->javascript(array('url' => 'script.js' )));
//$this->addHeaderItem($html->javascript(array('url' => 'headerjs.js', 'header' => '1')));


Edit site/config.php to enable:

define('ENABLE_ASSET_COMPRESSION', '1');


Caveats:

- I tried to get it to work while a user is logged in, but for now, this will only be enabled on the public site.

- You may need to edit your block controller files to include JS at the footer or it may break. Look in /blocks/blockname/controller.php for the on_page_view() function and use the new method to insert JS.

Example from Google Maps block:
$this->addHeaderItem($html->javascript(array('url' => 'http://maps.google.com/maps/api/js?sensor=true')));


Hopefully this will be useful to others and I think it's a pretty good solution as:

- minify caches its output
- concrete5 is only generating the links, not processing the files

Please test it out and let me know if you find any issues.

* I made an error in header_required and the examples above which led to 'CORE' not being passed with addHeaderItem. This caused jQuery and ccm.base* to not load at the beginning of the header which could cause problems. The attachment and examples are now fixed.

1 Attachment

xenyz
 
pixelhandler replied on at Permalink Reply
Using Minify scripts with concrete5 (http://code.google.com/p/minify/... )... I am having trouble with the minify groups :

I use minify on my other sites and link to groups like : /min/?g=plugins and with Minify_groupUri('plugins') the code generates a 'far-future' expires link with a numeric parameter following the link e.g. ?1133498792 but I can't seem to get the include path set to use the scripts in /min/lib with set_include_path did you use any Minify Classes ?

I had set_include_path($_SERVER['DOCUMENT_ROOT'] . '/min/lib' . PATH_SEPARATOR . get_include_path()); but the Minify classes aren't found in concrete5

# in header...

<?php
// set path for include
set_include_path($_SERVER['DOCUMENT_ROOT'] . '/min/lib' . PATH_SEPARATOR . get_include_path());
require_once $_SERVER['DOCUMENT_ROOT'] . '/min/utils.php';
// get links to minify groups
$cssUri = Minify_groupUri('theme_css'); 
?>
<link rel="stylesheet" type="text/css" href="<?php echo $cssUri; ?>" media="all" />


# in footer...

<?php
// include Minify scripts
require_once $_SERVER['DOCUMENT_ROOT'] . '/min/utils.php';
$pluginjsUri = Minify_groupUri('plugin_js'); // plugin_js or plugin_js_nomin
$themejsUri = Minify_groupUri('theme_js'); // theme_js or theme_js_nomin
?>
<script type="text/javascript" src="<?php echo $pluginjsUri; ?>"></script>
<script type="text/javascript" src="<?php echo $themejsUri; ?>"></script>
adamjohnson replied on at Permalink Reply
adamjohnson
xenyz replied on at Permalink Reply
xenyz
I did get the idea from a number of sources and the onehat blog was one of them. I do believe their code ended up in helpers/html/v2.php

I actually tried emailing them to get some feedback but nothing yet. I should have given them credit in the original post though.
PatrickHeck replied on at Permalink Reply
PatrickHeck
The Google CDN reference could also be added with a fallback in case remote loading fails:http://www.concrete5.org/community/forums/customizing_c5/fallback-f...
demotest333 replied on at Permalink Reply
This is all handy but If you really want to speed up your site and you are using a modern linux distro (e.g. CentOS 5.5) the built in concrete5 caching is perfectly fine.

Most performance tips ignore that you are still io bound, yes you make the cache smaller and more compact but still it's hitting a spinning disk platter which is really slow.

Most modern linux file distros now install by default an auto-expanding ramdisk at /dev/shm ... delete files/cache ... then symlink /dev/shm to files/cache and you'll be blown away by the speed increase.

As well, if you are using APC you can skip all the caching completely and just edit your php.ini to include "apc.stat=0" ... this tells APC to keep all php code cached eternally which means that your entire site runs out of memory. The only time you ever need to clear the apc cache is if you alter the concrete5 php itself and this is done by just restarting your web server (apache) or your php fastcgi process.

These tips have worked really well for us.
xenyz replied on at Permalink Reply
xenyz
Those are really good tips to get concrete5 running quicker on a host you control, but the original post was intended to help speed up page loading in the user's browser, independent of how fast concrete5 serves up the data. You could have a server send the entire page and assets in a second, but if the user's browser spends 5 seconds displaying the page because of js or css, your site is still 'slow'. I'm sure if you used these tips with yours you'd find your site going even quicker!

For those who don't have control over their web server, I wrote up a how-to in the developer's section a few weeks ago on speeding up c5 with another cache:http://www.concrete5.org/documentation/how-tos/developers/speed-up-...
meinprotein replied on at Permalink Reply
Hello xenyz

I need your help:

I have performed your instructions on the pagehttp://www.somandin.ch (Concrete 5.6.0.2).

That did not work (blank page).

So got back to the original files.

Unfortunately, I now get the following error message:


Warning: require_once (/ home / somancbh /http://www.somandin.ch / libraries / view.php) [function.require-once]: failed to open stream: No such file or directory in / home / somancbh /http://www.somandin.ch / concrete / core / libraries / loader.php on line 30

Warning: include_once () [function.include]: Failed opening '/ home / somancbh /http://www.somandin.ch / libraries / view.php' in / home / somancbh /http://www.somandin.ch / concrete / core / libraries / loader.php on line 30

Please help!

Thank you
Dan