Jump to content
Sign in to follow this  
init2null

Some ideas for asset optimization & preprocessing

Recommended Posts

I've gotten a little obsessed with the page loading time on my latest website. Many of you use AIOM for asset preprocessing, but I decided to use Grunt and htaccess for more control and a lighter server burden. Here are the techniques I used in a random order:

For file versioning, I supply distant expiration dates and use this line in my htaccess: RewriteRule ^([^.]+)\.[0-9]+\.([^.]+)$ $1.$2 The file is referenced as "myfile.<?php echo filemtime("myfile.js"); ?>.js", though I do this in a function for additional path translation. MD5 would be another option, but it would take longer.

For both Javascript & CSS (first converted from LESS), I first combine the multiple support libraries into one file. I include these files on the server as *.src.*; the templates includes the *.src.* files when the viewer is superuser. I then minify them and include them as *.min.*. I use Grunt to compress them all as *.*.gz and serve them as needed:

<IfModule mod_headers.c>
	# Serve gzip compressed CSS files if they exist and the client accepts gzip.
	RewriteCond %{HTTP:Accept-encoding} gzip
	RewriteCond %{REQUEST_FILENAME}\.gz -s
	RewriteRule ^(.*)\.css $1\.css\.gz [QSA]
	# Serve gzip compressed JS files if they exist and the client accepts gzip.
	RewriteCond %{HTTP:Accept-encoding} gzip
	RewriteCond %{REQUEST_FILENAME}\.gz -s
	RewriteRule ^(.*)\.js $1\.js\.gz [QSA]
	# Serve correct content types, and prevent mod_deflate double gzip.
	RewriteRule \.js\.gz$ - [T=text/javascript,E=no-gzip:1]
	RewriteRule \.css\.gz$ - [T=text/css,E=no-gzip:1]
	<FilesMatch "(\.js\.gz|\.css\.gz|\.svgz)$">
		# Serve correct encoding type.
		Header set Content-Encoding gzip
		Header set Precompressed true #for debugging
		# Force proxies to cache gzipped & non-gzipped css/js files separately.
		Header append Vary Accept-Encoding
	</FilesMatch>
</IfModule>

I needed to provide the main script with arguments but wanted to load the Javascript using the async keyword, so I assigned the arguments as global variables and access them when JS finishes loading.

I found many ways to use SVG in this design, and I aggressively optimized the illustrations and the generated code. Editing the XML by hand can shave several kilobytes off the file. In one case, I reduced the file size from 40 KB to 4. I also use Grunt to pre-compress it as with the JS and CSS. If you're really obsessive, you can rearrange the SVG attributes for better compression.

These may be basic tips for most of you, but I'm hoping they'll be helpful to someone. For anyone interested, I've attached the Gruntfile. I only ask that you don't judge the file structure too harshly.

Since I probably haven't scratched the surface here, feel free to provide any of your own tips.

gruntfile.js.txt

  • Like 5

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By MuchDev
      Hey guys, I know this isn't really a how to, but I am currently working on a system to inline above the fold css and was needing a json pagelist, and figured I would write something to automate it. I included the ability to flatten the tree or keep it expanded. There is also a filter section where you can exclude individual pages by path, parent, id, or template. This is all pretty bare bones and will pretty much just gives you a json array of your page paths, but that is all I needed. This is working code but you will need to clear out the filters for your own site. 
      <?php /* * JSON SITEMAP GENERATOR * By Sam Fleming -- MUCHDEV * This will create a json sitemap for grunt or other purposes * * option includes flat / expanded. Use however you need * * apply whatever filters you need to exclude in the filter array * curently supports excluding by: * Path * Parrent * ID * Template */ ########################################################### ## SET HERE IF YOU WANT AN EXPANDED OR FLATTENED SITEMAP ## ########################################################### $flatten = true; ########################################################### ## YOUR PAGE FILTERS GO HERE ## ########################################################### $filters = array(     "paths" => array(         "/processwire/"     ),     "parents" => array(         "3211",         "5",             "55",         "98745"         ),     "ids" => array(         "1123",         "5985",         "321454",         "15885",             "321115",         "39"                 ),         "templates" => array(         "template1",      "template2"     )     ); function buildSitemap($flatten) { $home = wire('pages')->get('/'); $urls[] = $home->httpUrl; $urls[] = getChildren($home->children); if($flatten){ $flatArray = arrayFlatten($urls); return json_encode($flatArray); }else{ return json_encode($urls); } } function getChildren($pages){ foreach($pages as $page){ //iterate through all the filters in array, and if the type matches then set flag to true $flag = false; foreach($filters as $filter){ switch($filter){ case "paths": foreach($filter as $path){ if($page->path == $path) $flag = true; } break; case "parents": foreach($filter as $parrent){ if($page->parrent == $parrent)$flag = true; } break; case "ids": foreach($filter as $id){ if($page->id == $id)$flag = true; } break; case "templates": foreach($filter as $template){ if($page->template == $template)$flag = true; } break; } } if(!$flag) $urls[] = $page->httpUrl; //if page has children then recurse if($page->numChildren){ $urls[] = getChildren($page->children); } } return $urls; } function arrayFlatten($array) { $return = array(); foreach ($array as $key => $value) { if (is_array($value)){ $return = array_merge($return, arrayFlatten($value)); } else { $return[$key] = $value; } } return $return; } echo buildSitemap($flatten); ?>
×
×
  • Create New...