Cascading Style Sheet and JavaScript Versioning
The problem
Let’s say you have a page with some complicated layout:
You go into the HTML and CSS files and make a slight change and when you reload the page you get this:
Why did this happen? Well, if we look at the network tab of the Developer Tools in Chrome:
You will see the following row:
The problem is happening because of what’s displayed in the sixth column that says “(from cache)”. The browser is using it’s cached version of the CSS file which causes the layout to go all haywire (new version of HTML + old version of CSS). It’s easy enough to fix by forcing a refresh of the page which causes all the files to download again and fixes the problem. But what if you’re users don’t know this fix? Then it just looks like your sites is broken and who wants to pay for a broken site. Even worse, what if the JS doesn’t match up causes a validation to fail and data is lost?
A Good Solution
A very, very fast solution to this problem is to just create a version number for the files and append it to the file name in the HTML:
style.css?version=1.1.3
When you update the version number in the HTML file the browser will see it as a new version of the file and download it instead of using the cached version. The only downside to this is that you need to remember to update the version number or write a script to update it before you deploy the site (I would recommend the script).
This works extremely well if you’re serving a static site because it can be done once and will be extremely fast.
A Better Solution
If you need a quick fix to this problem and have static files that change regularly you can append the modified time of the file to the file name in PHP this would be done using the following:
echo 'print.css?', filemtime('/path/to/print.css');
This would result in the following output:
print.css?1340220984
Then when you update the file the “version” is automatically updated for you:
print.css?1340223233
The Best Solution
According to High Performance Web Sites: Essential Knowledge for Front-End Engineers (and I agree with it) the best solution to hosting JS and CSS files is to have few external JS files for each page and few external CSS files for each page. This will drastically reduce the number of requests each pages makes and improved the front end performance of your website (as well as reduce the load on your servers on the backend).
The solution I have come up with is to create a class that takes a series of JS and CSS files and concatenates them all together and performs the following actions to minify the page so there aren’t any wasted bytes:
- Remove comments
- Convert return characters to spaces
- Convert multiple whitespace characters to a single space character
The result of this process will get a unique name based on the oldest modification time of the input files which will then get linked to in the HTML.
A slightly better solution is instead of having a single JS and CSS file for each page you create a single JS/CSS file for the generic elements of the site and then have individual JS/CSS files for each module/section so you don’t cause the user’s browser to download a lot of data it doesn’t need.
When implementing this it’s important to have a way to keep the files from being regenerated every time the pages are generated. I would recommend placing all the files in a common directory and importing them all at once. Then once the output has been created place a flag file in the same directory that contains the new filename and when you deploy the site delete these files so a rebuild happens.
Scott Keck-Warren
Scott is the Director of Technology at WeCare Connect where he strives to provide solutions for his customers needs. He's the father of two and can be found most weekends working on projects around the house with his loving partner.
Top Posts
- Working With Soft Deletes in Laravel (By Example)
- Fixing CMake was unable to find a build program corresponding to "Unix Makefiles"
- Upgrading to Laravel 8.x
- Get The Count of the Number of Users in an AD Group
- Multiple Vagrant VMs in One Vagrantfile
- Fixing the "this is larger than GitHub's recommended maximum file size of 50.00 MB" error
- Changing the Directory Vagrant Stores the VMs In
- Accepting Android SDK Licenses From The OSX Command Line
- Fixing the 'Target class [config] does not exist' Error
- Using Rectangle to Manage MacOS Windows