Skip to content

Instantly share code, notes, and snippets.

@ktheory
Created April 2, 2014 23:03
Show Gist options
  • Save ktheory/9945101 to your computer and use it in GitHub Desktop.
Save ktheory/9945101 to your computer and use it in GitHub Desktop.

Rails Asset Pipeline + S3

The asset pipeline changed a bit in Rails4, and I've never been super happy w/ the egads approach to tar'ing assets.

So here's my idea for a better approach.

Features:

  • Assets are only built once per SHA. (Deploys are fast.)
  • Old assets remain accessible on S3 (say, for emails)
  • Minimal compiling/uploading/downloading locally and on deployed servers. (FAAAASSSSTTT!)
  • Generally applicable to Rails app, OSS gem. Move Rails deploy practices forward.

How it works

Keep compiled assets, manifest files on S3.

Manifest files are named for the git SHA from which they're generated (e.g., /kickstarter/123abc_manifest.yml)

All deployed environments use the same asset host (CloudFront to S3)

At deploy time or on the CI server, we run prepare_assets

prepare_assets script:

  1. Checks if the manifest for that SHA exists on S3. If so, we're done.
  2. Otherwise, generate the manifest & associated assets
  3. Diff the manifest from a recent manifest for that branch to determine new assets
  4. Upload the new (missing) assets to S3.
  5. Upload the manifest file to the SHA and branch name. (Branch name for efficient diff'ing)

Manifest files are private (authenticated urls to download); everything else is publicly readable.

On deployed servers, we run fetch_manifest script:

  1. Download the manifest file for that SHA from S3. Trust that all the referenced assets exist.
  2. If for some reason the manifest doesn't exist, fall back to compiling assets on the deployed server?

So deployed servers will just have the manifest, but not necessarily have the actual assets. But I think that's ok??

@tiegz
Copy link

tiegz commented Apr 28, 2014

excellent! Question: by manifest file, do you mean the Sprockets manifest file?

@tiegz
Copy link

tiegz commented Apr 28, 2014

Just asking because the manifest filename/path are hard-coded in the new versions... we could monkeypatch it of course too:

@path = File.join(@dir, "manifest-#{SecureRandom.hex(16)}.json")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment