Online and offline development with the YUI and Charles

Now that all yui library files are publicly hosted on it makes sense in any project you are working on to link the files from these locations. Given the widespread usage of the yui, if a user has already got any of these files in their cache you are saving them downloading the files afresh.

One of the issues with this is what happens if you need to work offline at any point. Say you are taking a flight and just have an idea how to fix something that you are working on, you break out your laptop and then you find that none of your js is working because the yui libraries are linked to Well one solution to this would be simply change the path. But if you regularly work offline this won't take long to become a pain in the neck. Also if you need to share code with several people you can't necessary stick a conditional around the script includes.

The quick way to save yourself changing links all the time is to use the request re-write facility in Charles. Charles is fantastically useful cross-platform http debugging proxy and well worth buying if you are spending any time working on websites and web apps. One of it's features is the ability to re-write requests on the fly. Through this method we can use some simple regex to re-write a request to to point at yui files in your localhost development environment e.g. MAMP/XAMP etc.

How to Configure Charles for request re-writes.

First open the rewrite window. What I did was set-up a group for yui js files. The glob style wildcard is simply set as*.js.

Next you need to add a rule. The settings are as follows.

Match Value:
http://.*?([^/]*?.js) (Make sure regex is ticked)
New :
http://localhost:8888/yui/$1 (Make sure replace all is selected)

Here's a screenshot of the configuration of the rewrite screen.

As you can see this re-writes any js file called from to the same js file in http://localhost:8888/yui/.

Placing all the YUI files in one directory

When you download the YUI library you will notice that each of the library files are in their own directory inside 'build'. We could replicate this structure for our re-write but I find that if I want to build a prototype quickly using the YUI then I want just dive straight in and drag and drop a file into textmate. To make this easier than manually moving the files around this I created a simple Python script that recurses through the YUI src files and symlinks (or copies on windows) the normal non-minimised files into one directory for ease of use. This set-up also helps with what we are doing in this case.

To use the script you'll need to edit the two path variables in the file. The first points to the build directory of the yui files and the second is where you want the files to be linked to. If you update the yui later you can simply dump the existing files and run this script again.

#!/usr/bin/env python
import os, string, sys, shutil, re

pathtobuild = '/Volumes/HomeVault/htdocs/yui_src/build/'
pathtolink = '/Volumes/HomeVault/htdocs/yui/'
#pathtobuild = 'C:/Documents and Settings/Administrator/Desktop/yui/build'
#pathtolink = 'C:/Documents and Settings/Administrator/Desktop/yui'

def linkOrCopy(path,filename):
  if sys.platform != 'win32':
    os.system("ln -s "+path+"/"+filename+" "+pathtolink+"/"+filename)
    shutil.copy(path+"/"+filename, pathtolink+"/"+filename)

def traverseDir(path,regex=''):
  files = os.listdir(path)
  path = path[-1] != '/' and path or path[0:-1] #do we need a trailing slash or not?

  for filename in files:
    if os.path.isdir(path+'/'+filename):


For my purposes I want the un-minified javascript files along with the minified CSS files. This way if I want to refer to the source code for any of the library files I can easily do so. Also I do this because minimisation is taken care of by using Ed Eliot's combine.php

If you'd prefer tp have just the minimised js files simply edit the regex as necessary. In this case it would be '.?min.js|.?min.css'

Now when you hop on the train or flight you can simply turn on the charles and your yui dependant js will still work as expected.