I've written twice about using Amazon S3 to host your website's static content. It's a great solution for small websites without access to a real content delivery network. And now that Amazon has launched CloudFront on top of S3, it's even better.
But there are still ways we can improve the performance. The trick is to upload our files using custom headers so they're served back with a proper expiration date and gzipped when possible — i.e., the techniques recommended by YSlow.
I've written a command line tool which simplifies this process called
s3up. The idea is simple. It uploads a single file to S3, sets a far future expiration date, gzips the content, and versions the file by combining the filename with a timestamp. Each of these actions are optional and can be controlled via the command line.
The basic syntax:
s3up myS3bucket js/somefile.js somefile.js
somefile.js into your Amazon S3 bucket named
myS3bucket inside the
We can build on this command by adding the
-x flag, which tells
s3up to set a far future expiration header. By default, it chooses a date ten years in the future:
s3up -x myS3bucket js/somefile.js somefile.js
This lets the browser know to keep the file cached indefinitely.
-z flag uploads two copies of the file. One normally, and a second that is gzipped and renamed
filename.gz.extension. You can then dynamically serve the compressed version to browsers that support it.
-t flag uploads and renames the file
filename.YYYYmmddHHmmss.extension. This lets you easily create versioned files when you need to update an existing file. (You need to use a new filename since the browser was told earlier to always load from the cache.)
Combining all three options we get:
s3up -txz myS3bucket js/somefile.js somefile.js
This uploads your file, compresses it, sets the correct expiration date, and versions the filename — all in one easy step.
If you'd prefer to choose your own string for versioning, you can specify it with the
s3up -txz --version=v2 myS3bucket js/somefile.js somefile.js
In that example, the file would be stored in S3 as
s3up also echoes the new filename so you can quickly paste it into your HTML. If you're on a Mac, you can automatically copy the new name onto your clipboard by piping
s3up to the
If you'd like to take this a step further and integrate
s3up into your existing deploy scripts, you can leave off the filename argument and instead pipe the data to upload via stdin. So, if you're using another tool like the YUI Compressor or byuic, you can run:
somecommand | s3up -txz myS3bucket js/somefile.js | pbcopy
Uploading Multiple Files
A common task is uploading a whole folder of images. You can do this in one step by appending a slash (/) to the S3 filename and using wildcards to specify multiple local files. Example:
s3up myS3bucket images/ /path/to/your/images/*.jpg
images/ ending with a slash, it treats it like a directory and stores all of your files into it. Make sure you remember the slash on
images/. That's what triggers the special "directory" mode uploading.
You can grab the latest copy of
s3up from the its GitHub project.