Develop Locally, Use Images from Production

Working on your website locally means having the files that make your website tick right there on your computer. It's common those files live in a version control repository. You work on them, and push them up to the repo when you are ready. Other people work too, and you pull their changes back down.

What might not be in that repo, are images files from the CMS. WordPress is a classic example of this. When you upload an image in WordPress, it does a whole song and dance. It gets uploaded to the `uploads` folder, multiple versions are created, even the database is updated and attachment meta data happens. What doesn't happen is that a version control commit happens with all those files.

There are ways to make sure you have those files. You could write a script to pull them down. You could manually FTP it once in a while. In WordPress land, there are plugins that help, like WP DB Migrate Pro, which not only does the database but can move images as well.

But you might not even want to deal with images. Perhaps:

  • You don't want the images in your repo. Maybe the repo is just a theme folder and it makes sense to leave it that way.
  • You have like 10 GB worth of images and it's impractical and unnecessary to move them around.

I think that's totally legit. A publication-style site probably doesn't need every single image they've ever uploaded as part of their main repo.

OK, enough explanation. You get it.

Sean Lange talked about this exact thing in his 2013 article Using Remote Image Files When You Develop Locally. His solution was to rewrite local URL's at the web server level to point to the production files:

I found my answer in Apache URL rewrite rules. When the Apache program handles incoming web page requests, rewrite rules allow it to change URLs matching certain patterns -- for example, they can turn requests for the 'files' directory on your local machine into requests for remote URLs on the production server.

Here's his Apache rewrite rules:

RewriteEngine on
# Force image styles that have local files that exist to be generated.
RewriteCond %{REQUEST_URI} ^/sites/([^\/]*)/files/styles/[^\/]*/public/((.*))$
RewriteCond %{DOCUMENT_ROOT}/sites/%1/files/%2 -f
RewriteRule ^(.*)$ $1 [QSA,L]
# Otherwise, send anything else that's in the files directory to the production server.
RewriteCond %{REQUEST_URI} ^/sites/[^\/]*/files/.*$
RewriteCond %{REQUEST_URI} !^/sites/[^\/]*/files/css/.*$
RewriteCond %{REQUEST_URI} !^/sites/[^\/]*/files/js/.*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$$1 [QSA,L]

He's working with Drupal through MAMP, but so long as you're using Apache locally it's all just a variation on the same idea. Match URL's that point to the assets you want to target, rewrite them to the live site.

He was able to paste those rules into a little box in MAMP that handles it. I'm running WordPress locally through a little Docker setup, so I went for just editing my `.htaccess` file directly, and kinda simplified it for my needs:

RewriteCond %{REQUEST_URI} ^/wp-content/uploads/[^\/]*/.*$
RewriteRule ^(.*)$$1 [QSA,L]

Works great for me! Here's a visual explanation: