Let's get starting. Supposing you have a 900 lines CSS file that you use in your pages to define styles. It's kinda a big because, you added and added new things that needed a style, you like to impress your visitors with some visual effects and there you have it. A huge file. The main problem is that you don't use all the styles on every page so I will ask you to identify those classes and split the original 900 lines file into more files. Write down where and what you use and we have a good start. To take every page and include file B and file A and then on another page include file B without file A but file C would result in a total mess. Maybe not at the start but it will as you will start to update your pages and forget to include something. You will discover forgotten pages that your visitors use every day as being way behind of your actual configurations. Not to mention the number of HTTP requests that will have an effect on the load speed and also not to mention the big bad, ugly header of out page that uses so many requests to files. You get the idea.
In this article I will teach you hot to go from a huge header full of styles and js files, a big number of requests that the browser has to do, a massive amount of data that needs to be readed (and this contains white spaces, coding comments and other stuff like that)
Example:
To a well optimized and compressed one without even touching or changing our files. We keep the comments that help us, we keep the white spaces and tabs to keep the code intact and original - easy to follow etc but we output a compressed code to our visitor and all this for a better browsing experience and a good effect on our business.
Example:
Ed Eliot published a very interesting article about merging and versioning CSS and JS files into one file. At first you would think that it will result with a total mess but it's so wrong.
He also created a PHP script which does an excellent job. It takes all your JS or CSS files (that you previously specify in your settings) and combines them together into a single file without changing the original code or any of those files. It just reads the data and writes it into another file that will be used by the visitor's browser. You would ask why is that necessary. It will increas your website loading speed because you will have only one HTTP request instead of 5 or 6 or more and less (depending on your application).
We all know that browsers use a cache which is used to display the layout and styles after it was loaded once so it would seem to be a bad idea to use this script. That's once again...wrong. The same script uses a directory to save the files in and there's more. It checks to see if your browser has a cached file already and if it has and also that file would be no different than a newly created one it will bypass this process and let you use the cached one. That's an awesome tool if you ask me.
There's even more and this is the part when everything gets very interesting. I have written some days ago an article about how to compress your CSS code without touching a single line. The code will remain the same but the browser will see it without comments, white spaces, sooooo highly parsed and compressed. I tested a 921 file and it came out with 231. from 15 to 11 kb. How's that for good news?! Not good enough because there's more I'm going to talk about.
Yesterday, I had an idea. What if...I will combine this 2 great tools. One that will get together all the CSS files into one file and one that will compress it before creating the new file. Would it work?! Of course it did and such a great result. I looked at the created files and all my styles were there; compressed, parsed, no comments, no empty lines no nothing..nada! Just code! My original files are also intact; with my comments to help me out, with the original layout and tabs. This is the best thing I've ever found in months. I keep saying that but...look at this. I've managed to save almost 20% of the size of those files and the code is intact and functional.
What we achieved:
Lowered the HTTP requests to a number of 2 - one for the css file and the other one for the js files
A smaller code in our page - everything is inline, in a single file, our page source is smaller
Parsed and compressed our files - we reduced the size up to 20%
Increased the loading speed and optimized our web page for a better user experience - we still have to think about modems. If a page that is loading in 5 secs. seems fast today it will be slow tomorrow so we're always in the search of web page optimizers.
Here's the code that was changed in order to compress the css files (please remember that it's only for css code. I haven't tested it yet on javascript. If you want to use and combine multiple js fles into one click here for the original code.):
- <?php
- // Written by Ed Eliot (www.ejeliot.com) - provided as-is, use at your own risk
- //This script was modified by Mihalcea Romeo from roscripts.com in order to output a more compressed file without touching the original files used.
- //
- /****************** start of config ******************/
- define('FILE_TYPE', 'text/css'); // type of code we're outputting
- define('CACHE_LENGTH', 31356000); // length of time to cache output file, default approx 1 year
- define('CREATE_ARCHIVE', true); // set to false to suppress writing of code archive, files will be merged on each request
- define('ARCHIVE_FOLDER', 'cache'); // location to store archive, don't add starting or trailing slashes. Remember to CHMOD this to 0777
- // files to merge
- $aFiles = array(
- 'css/your_css_file_here.css',
- 'css/your_css_file_here1.css',
- 'css/your_css_file_here2.css',
- 'css/your_css_file_here3.css',
- 'css/your_css_file_here4.css',
- 'css/your_css_file_here5.css',
- 'css/your_css_file_here6.css',
- 'css/your_css_file_here7.css'
- );
- /****************** end of config ********************/
- // this is prepended to all file / folder paths so files and archive folder should be specified relative to this
- $sDocRoot = $_SERVER['DOCUMENT_ROOT'];
- /*
- if etag parameter is present then the script is being called directly, otherwise we're including it in
- another script with require or include. If calling directly we return code othewise we return the etag
- representing the latest files
- */
- if (isset($_GET['version'])) {
- $iETag = (int)$_GET['version'];
- $sLastModified = gmdate('D, d M Y H:i:s', $iETag).' GMT';
- // see if the user has an updated copy in browser cache
- if (
- (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $_SERVER['HTTP_IF_MODIFIED_SINCE'] == $sLastModified) ||
- (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $iETag)
- ) {
- header("{$_SERVER['SERVER_PROTOCOL']} 304 Not Modified");
- exit;
- }
- // create a directory for storing current and archive versions
- if (CREATE_ARCHIVE && !is_dir("$sDocRoot/".ARCHIVE_FOLDER)) {
- mkdir("$sDocRoot/".ARCHIVE_FOLDER);
- }
- // get code from archive folder if it exists, otherwise grab latest files, merge and save in archive folder
- if (CREATE_ARCHIVE && file_exists("$sDocRoot/".ARCHIVE_FOLDER."/$iETag.cache")) {
- $sCode = file_get_contents("$sDocRoot/".ARCHIVE_FOLDER."/$iETag.cache");
- } else {
- // get and merge code
- $sCode = '';
- $aLastModifieds = array();
- foreach ($aFiles as $sFile) {
- $aLastModifieds[] = filemtime("$sDocRoot/$sFile");
- $sCode .= file_get_contents("$sDocRoot/$sFile");
- }
- // sort dates, newest first
- rsort($aLastModifieds);
- if (CREATE_ARCHIVE) {
- if ($iETag == $aLastModifieds[0]) { // check for valid etag, we don't want invalid requests to fill up archive folder
- $oFile = fopen("$sDocRoot/".ARCHIVE_FOLDER."/$iETag.cache", 'w');
- if (flock($oFile, LOCK_EX)) {
- fwrite($oFile, compress($sCode));
- flock($oFile, LOCK_UN);
- }
- fclose($oFile);
- } else {
- // archive file no longer exists or invalid etag specified
- header("{$_SERVER['SERVER_PROTOCOL']} 404 Not Found");
- exit;
- }
- }
- }
- // send HTTP headers to ensure aggressive caching
- header('Expires: '.gmdate('D, d M Y H:i:s', time() + CACHE_LENGTH).' GMT'); // 1 year from now
- header('Content-Type: '.FILE_TYPE);
- header('Content-Length: '.strlen($sCode));
- header("Last-Modified: $sLastModified");
- header("ETag: $iETag");
- header('Cache-Control: max-age='.CACHE_LENGTH);
- // output merged code
- ob_start("compress");
- echo $sCode;
- ob_end_flush();
- } else {
- // get file last modified dates
- $aLastModifieds = array();
- foreach ($aFiles as $sFile) {
- $aLastModifieds[] = filemtime("$sDocRoot/$sFile");
- }
- // sort dates, newest first
- rsort($aLastModifieds);
- // output latest timestamp
- echo $aLastModifieds[0];
- }
- function compress($buffer) {
- // remove comments
- $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
- // remove tabs, spaces, newlines, etc.
- $buffer = str_replace(array("\r\n", "\r", "\n", "\t", ' ', ' ', ' '), '', $buffer);
- return $buffer;
- }
- ?>
Example usage:
- <link href="cache/site_<?php require('compressor.php'); ?>.css" rel="stylesheet" type="text/css" />
- <!--
- cache = the folder used for saving the created files
- compressor.php = this is the name of the file above presented that will compress the code and also combine our files into a single one.
- -->
A friend of mine told me an interesting thing. What if I use some files for some pages only and not in all my pages. This script will combine them all together but in many pages the code will never be used. No problemo. Here we get a little more complicated.
If we look at the code we have the following array:
- // files to merge
- $aFiles = array(
- 'css/your_css_file_here.css',
- 'css/your_css_file_here1.css',
- 'css/your_css_file_here2.css',
- 'css/your_css_file_here3.css',
- 'css/your_css_file_here4.css',
- 'css/your_css_file_here5.css',
- 'css/your_css_file_here6.css',
- 'css/your_css_file_here7.css'
- );
This is the part where we tell the script what files to use and compress. Let's say we have two pages. One called index.php where we want to use all the css files and one called something.php where we want to use only the first two css files. How do we do that?
Here's for that how question. We will use the "eregi" function from PHP to define some conditional statements (here's a full article on conditional statements and how to use them). We will create an example based on our needs.
- if (eregi("index.php", $_SERVER['PHP_SELF']) {
- $aFiles = array(
- 'css/your_css_file_here.css',
- 'css/your_css_file_here1.css',
- 'css/your_css_file_here2.css',
- 'css/your_css_file_here3.css',
- 'css/your_css_file_here4.css',
- 'css/your_css_file_here5.css',
- 'css/your_css_file_here6.css',
- 'css/your_css_file_here7.css'
- );
- } elseif (eregi("something.php", $_SERVER['PHP_SELF']) {
- $aFiles = array(
- 'css/your_css_file_here.css',
- 'css/your_css_file_here7.css'
- );
- }
Notice we used "elseif" in order to specify the other case where we will use a different array for "something.php" but we could leave it as just "else" and in this case the array will contain all the scripts for "index.php" but just the first two for the rest of our pages.
The last thing that we need to do is to modify out .htaccess file to tell our server where to look for the new CSS and JS files so we will create a small rule to be followed.
RewriteEngine On
RewriteBase /
RewriteRule cache/site_([0-9]+).css compressor.php?version=$1 [L]
RewriteRule cache/site_([0-9]+).js compressor_js.php?version=$1 [L]
Notice that I've used two files. "compress.php" for the css files and "compress_js.php" for javascript.
Thank you for reading this,
discuss this topic to forum
