Develop Simply

Ivan K's development musings

Kohana Assets Done Right

The big boys in the framework wold all have some ways of managing your assets - CSS and JS files with proper merging, cache busters, minification and all jazz. Kohana 3 on the other hand - has only some modest efforts. None of them have all the features that seems to be present elsewhere. And I don’t really have an explanation why - those are generally well known requirements for production sites. Anyway I was fed up with this state of affairs and I decided to just write my own solution. Here’s what my dream asset manager thing must do:

  • Merge arbitrary number of CSS and JS files into one file respectfully.
  • Different behavior in different environments - keep separate files in development and merge in production
  • Ease implementation of JS and CSS related languages - SASS, LESS, CofeeScript etc.
  • Minify all the files, but have the ability to chose exceptions
  • Ability to add small code snippets in between files so when they are merged in one big file it remains in the proper load placement.
  • Bonus points for easy API.

So I set of to implement all of this and more - and here is the fruit of a full day’s work - The Asset-Merger. Installation instructions

1
git clone git://github.com/OpenBuildings/asset-merger.git modules/asset-merger

Or

1
2
git submodule git://github.com/OpenBuildings/asset-merger.git modules/asset-merger
git submodule update --init

The documentation is quite adequate I think, and will get you up to speed, but here are just a few highlights

1
2
3
4
5
6
7
8
9
10
11
12
<?php echo Assets::factory('all')
  ->css('less/homepage.css.less')
  ->css('jquery-ui-1.8.custom.css')
  ->css('notifications.css')

  ->js("http://use.typekit.com/sdfhkas.js")
  ->js("http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js")
  ->js("http://maps.google.com/maps/api/js?sensor=false")
  ->js_block("try{Typekit.load();}catch(e){}")
  ->js("main/general.js")
  ->render();
?>                     

less/homepage.css.less

That’s right - Engines! Just how the big boys are doing it. You can even chain them for proper power effect.

less/homepage.css.less.php

It will get that you are including external files and it’s not a very good practice to download and inline them (they are placed remotely for a reason). So they just appear as proper link or script tag.

js_block(“try{Typekit.load();}catch(e){}”)

This will output a nice inline script tag but in PRODUCTION environment - it will be inlined inside the merged Javascript file. That’s right, no more messy javascript snippets inside your templates. Meaning that it will be cached along all your other assets in the browser cache.

And here’s a great simple touch that I haven’t seen anywhere else before but find immensely satisfying - you can do a

1
2
3
4
5
6
<?php echo Assets::factory('all')
  ->merge(TRUE)->process(TRUE)
  ->css('less/homepage.css.less')
  ->css('jquery-ui-1.8.custom.css')
  ->css('notifications.css')
?>

And see the result of your hard labor. I know you can probably switch the environment, and that’s probably better anyway, but to have a quick check if everything works correctly when its put together is quite nice.

Now, asset-merger utilizes filemtime checks to see if it needs to recompile the files, which might be a bit costly in a production environment. But you can always cache this part as a Kohana Fragment and live happy.

1
2
3
4
5
6
7
<?php if ( ! Fragment::load('assets', Date::YEAR, true)): ?>
  <?php echo Assets::factory('all')
      ->css('less/homepage.css.less')
      ->css('jquery-ui-1.8.custom.css')
      ->css('notifications.css')
  ?>
<?php endif; ?>

You can cache the hell out of it because you will probably clear your cache on deploy anyway.

I will be working on adding CDN support shortly.