Symlink CakePHP plugin assets for faster page loads

If you are a fan of CakePHP's plug-ins, and want to keep you application non-dependent on plug-ins you have to keep the assets in the plug-ins webroot folder. This might not seem like a bad thing till you realise CakePHP delivers those files via some fread() calls and appropriate headers.

So what you ask? Say You have an application with many plug-ins, things like a gallery, content management, some sort of WYSIWYG editor etc. Throw in a theme or two and you application is starting to look complete. Add a whack of images to the mix, be it products, avatars or just the general look and feel and you are good to go. The plug-ins define some sort of basic styles and Javascript interactions, while your theme joins them all together.

Most of them will have some sort of Javascript and style sheet, all needing to be dispatched to the user. For the most part the browser will cache the assets after the first call, and then only again when they have passed the set lifetime.

Enter Xhprof

If you have used Xhprof profiler before you may have noticed that one request is not really one request. That’s right, in the case of my site with a few extra plug-ins that I'm developing for Infinitas one request is actually about 55 requests through Php.

So what can you do about this? According to the book, one solution is copying the assets from the plug-in directory to the webroot folder. That will stop the requests going through php, but your plug-ins are no longer self contained, and your application is polluted with code from the plug-ins. Git will complain, maintenance is a pain and various other problems.

What is there to gain

Obviously once the browser has cached the files this is not a problem, but for new visitors, returning visitors for a while back and people clearing cache / reloading the page there is a huge difference.

Symbolic links ftw

So taking the other advice from the book, we decide to create some symlinks. For 30 or so plug-ins and endless themes typing out the commands in console (shell, prompt, cli or what ever its called) becomes a real pain. Even more so when you upload you newly created application to your clients shared hosting that does not have console access.

Being the lazy developer I am, I decided there needs to be some code do this for me. Wanting to be able to do it from the application its self, or from the CakePHP console, it needed to be in a lib. All you need to do is App::import() the lib into your code and then create a new instance of the class. You can use $Symlink->autoAssetLinks() to create links and $Symlink->autoAssetLinks(true) to delete them. There is also a method for listing what links are already created.

I have already done the code for the backend in Infinitas here. At a later stage I'll add some shell tasks. This is the final result: (note the request time)

The Code

I just pasted it to a gist for ease, I will not be maintaining this, so check out the up-to date stuff in the Infinitas repo

More

Now I'll work on some asset compressing and joining, then its only one request per asset type, as opposed to the bunch its currently doing. Hopefully it will work out better that the Google one I tried :P

bartgon 26/3/13

Hi Carl, thanks for pointing me to the proper Utility! I'll dive into it.

best
Bart