Using the below techniques you can speed up your site's page load time. My testing has a site going from ~4.5s to ~2s per page load, YMMV.
The first section is getting Minify working, and the second section is installing and configuring BootstrapCache.
Download these two packages and copy Minify to /min and BootstrapCache to /libraries/bootstrapcache and make the change in /concrete/dispatcher.php. Go to the forum link and download the attachment. Put the files in the respective folders in the site root.
Minify
Taking a look through libraries/view.php I found some commented out code to use 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)
To get it to work, 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')));
I think it's a pretty good solution as:
- minify caches its output
- concrete5 is only generating the links, not processing the files
BootstrapCache
You may need to make two small changes depending on whether or not your web host allows access to the /tmp directory. I would make the changes anyway since /tmp may be cleared at any time and your cache lifetime may be set to never expire.
Open /libraries/bootstrapcache.php and find the line:
define('CACHE_LOCATION', '/tmp/');
Change to:
define('CACHE_LOCATION', DIR_FILES_CACHE);
Open /libraries/bootstrapcache/cachelite/Lite.php and add before class Cache_Lite:
if (!defined('CACHE_LOCATION')) {
define('CACHE_LOCATION', DIR_FILES_CACHE . "/");
}
Find:
var $_cacheDir = '/tmp/';
Change to:
var $_cacheDir = CACHE_LOCATION;
Edit /config/site.php to enable the cache:
define('BOOTSTRAPCACHE', true);
define('BOOTSTRAPCACHE_DEBUG', false);
// set the default cache time in seconds, null means indefinitely cache
define('BOOTSTRAPCACHE_DEFAULT_CACHE_TIME', null);
You can use the debug switch to see if the cache is working, but you should be able to tell from the new page loading speed.
Caveats:
Disable the concrete5 built-in cache and enable pretty URLs as per the instructions of the BootstrapCache author (posted above and here). Read the full caveat list on the page as well!
BootstrapCache flushes the cache when you sign in, so you will need to navigate around the site to prime the cache after signing out. Another method is to use wget to spider your site to prime the cache:
wget -r -nd --spider -R txt,js,css,jpg,png,gif http://example.com
There is an issue with the cache interfering with 404 pages; instead of page_not_found loading it redirects to the home page.
You may need PHP 5.3 for BootstrapCache
Page Load Speed
It's a good idea to test your site before and after at webpagetest.org to see what kind of real world speed improvements you're getting.
Hopefully others can get some use out of what I've learned in the past week trying to speed up a concrete5 site. Fast page loads are almost necessary these days!