Blog» JavaScript and CSS caching best practices with ezjscore and eZ Publish

JavaScript and CSS caching best practices with ezjscore and eZ Publish

By Peter Keung  | October 20, 2015  |  eZ Publish development tips, Site performance

A good caching system keeps elements in the cache as long as possible, but clears them as soon as the elements are updated. For content pages in eZ Publish and most content management systems, "purge-on-publish" features are well documented. When it comes to JavaScript and CSS files, there are usually different caching systems involved, and these are important to configure. Otherwise, you'll end up with the all-too-familiar problem of a broken front-end on deployments, where the only fix is to have users do a "hard refresh" (CTRL+F5) in the browser.

With eZ Publish (legacy), the ezjscore extension is critical for loading, concatenating, and minifying JS and CSS files. It places the generated JS and CSS files in the /var/[site_name]/cache/public/ folder.

You can instruct browsers to cache these files for a long time with an Apache configuration such as this:

<LocationMatch "^/var/[^/]+/cache/public/.*">
# Force ezjscore packer js/css files to be cached 90 days at the client side
ExpiresActive on
ExpiresDefault "now plus 90 days"
SetOutputFilter DEFLATE
Header merge "Cache-Control" public
</LocationMatch>

If you are using a CDN or reverse proxy (such as Varnish) you'll also want an equivalent rule so that the server- or edge-side caching layer keeps those files for a long time.

When you modify a JS or CSS file, you want users to get the changes immediately. If the same JS and CSS file names are referenced by your website pages, then you have to worry about clearing the cache at the CDN or reverse proxy level and also at the browser level. It is also not possible to force all users to clear their browser cache. Therefore, you can instruct ezjscore to generate new file names whenever the eZ Publish cache is cleared with this setting in an override of ezjscore.ini.append.php:

[Packer]
AppendLastModifiedTime=enabled

This will make the JS and CSS file names something like this, with a timestamp appended:

/var/mugo/cache/public/stylesheets/cba6be1d1c03cdc0990e4246102a7a21_1444940081_all.css

The additional complication is with cached pages that still reference the old JS and CSS file names. You don't want to have to clear your entire site's page caches (especially at the CDN or reverse proxy level) whenever a JS or CSS change is released, so you have to consider that a stale cached page is still relevant -- not a desirable situation, but sometimes necessary. Unfortunately, when you clear ezjscore's cache, this removes all old generated JS and CSS files and can break those old links. With some additional configuration, you can keep these old generated files (who have file names that don't clash with your new generated files) on your server a bit longer. To do so, you'll need a new PHP class that will only delete generated files that are older than a certain amount of days. This example works for eZ DFS cluster configurations.

(Note: an alternative is to have an even longer caching time for JS and CSS files at your CDN or reverse proxy, but it is riskier as you could have cache expire earlier than expected if, for example, you have to restart your reverse proxy.)

First, add the following configuration to an override of site.ini.append.php:

[Cache_ezjscore]
class=MugoJSCCacheManager
# maxage is the maximum age a packed ezjscore .css or .js is allowed to be
# This is used to preserve the packed files for the timespan indicated
# Use any time that will work well with strtotime, for example "90 days"
# Do not use a minus sign - one will be added by the code
maxage=90 days

Then, your new PHP class should have a function called clearCache() that does the following:

<?php
class MugoJSCCacheManager {
 
    /**
    * Expires the ezjscore public cache folder by deleting all files that are more than 90 days old
    * @param array $cacheItem
    */
    public static function clearCache(array $cacheItem) {
        $ini = eZINI::instance();
        if ($ini->hasVariable("Cache_ezjscore", "maxage")) {
            $maxAge = "-" . $ini->variable("Cache_ezjscore", "maxage");
        } else {
            $maxAge = "-90 days";
        }
        $maxAge = strtotime($maxAge);
 
        // Get the existing JavaScript and stylesheet files
        $clusterHandler = eZClusterFileHandler::instance();
        $existingFiles = $clusterHandler->getFileList( array( 'ezjscore' ) );
 
        $pathUpdate = eZSys::rootDir() . '/';
        $fileIni = eZINI::instance('file.ini');
        if ( $fileIni->hasVariable( "eZDFSClusteringSettings", "MountPointPath" ) ) {
            $pathUpdate .= $fileIni->variable( "eZDFSClusteringSettings", "MountPointPath" ) . '/';
        }
 
        // Loop through all the existing files
        foreach ($existingFiles as $file) {
 
            // Get the modified time for the file
            $fileTimestamp = filemtime($pathUpdate . $file);
 
            // If the timestamp is before than $maxAge
            if ($fileTimestamp < $maxAge) {
                eZClusterFileHandler::instance()->fileDelete( $file );
                unlink( $pathUpdate . $file );
            }
        }
    }
}

With that in place, you can be sure that visitors will always get a properly formatted page -- using the new JavaScript files and stylesheets, or a valid older set until all page caches have expired.


Join our mailing list for news, events, tips, and tools

Related Blog Posts

Built-in Varnish Cache "purge-on-publish" support in eZ Publish

eZ Publish 5 comes with built-in Varnish Cache support. Essentially this means that when content is published in the eZ Publish back-end, it notifies Varnish...

Read more »

Using Varnish to speed up eZ Publish websites

Varnish Cache is a powerful website caching system that dramatically increases your site's performance. It does so by sitting in front of your Apache,...

Read more »

eZ Publish websites for publishing companies

Over the years we've worked on many websites in the publishing industry. Each has a unique set of requirements and challenges, but we've been able to...

Read more »

JavaScript and CSS in eZ Publish 5

A key component of a content management system or web application is the handling of JavaScript and CSS files, specifically around loading, combining,...

Read more »

Comments

blog comments powered by Disqus

Hi, we're Mugo Web - Nice to meet you!

We're a group of web experts who solve complex web problems.

Learn more about us »

Search


Categories


Yes - we can do that.

Many years of experience with complex websites allows us to offer total solutions.

Learn more about what we can do »

We love our clients (and they love us too)

We've solved problems across North America and around the world.

Learn more about what we've done »

We tweet too

Follow us on Twitter for the latest Mugo happenings

mugo twitter page @mugo

© 2008 - 2019 Mugo Web. All rights reserved.