Bulk Image Optimization in Shopify
When considering the performance of Shopify sites, images are often one of the main contributors to poor load times. In this tutorial, I'll outline our process for optimizing all the images which are part of the theme assets.
a note on images in Shopify: Images in Shopify can be stored in three locations. There are backend images, associated with admin-accessible "objects" like blog posts, collections, products, and variants. Next, there are images entered through the Theme Editor or "Customizer", which can also be uploaded and managed under Settings > Files. Lastly there are theme images, which are pulled from the theme's asset folder. There are many image optimization apps for Shopify, but I haven't seen one which can handle all three types. Especially with custom developed or older themes it's often necessary to optimize these directly.
We'll be using the following tools:
- terminal - macOS bash command line to run themekit (also available on windows)
- themekit - connects to shopify api to pull down and push up theme files
- imageoptim - great tool that uses a variety of algorithms to optimize common image formats
- sublime - text editor good for multi-select
First you'll need to create a working directory, get app credentials, and set up config.yml. There's nothing fancy to the working directory - just an empty folder for you to work in. Create the folder, and navigate to it in a terminal window. Create a text file called config.yml. This is what themekit uses to authenticate (gain access), know which store, and which theme to pull from.
Using terminal this looks something like this:
mkdir storename cd storename touch config.yml
Next paste in the following code which has the exclude patterns we use to ignore non-image assets:
development: password: <api password> theme_id: "<theme id>" store: shop-name.myshopify.com ignore_files: - "*.liquid" - "*.js" - "*.css" - "*.scss" - "*.json" - "*.svg" - "*.html" - "*.tff" - "*.eot" - "*.woff"
Then, replace the fields at the beginning with your particulars. Theme ID can be found by going to Themes > Customize and then looking at the number in the url. API Key is found by going to Apps > Manage Private Apps. Create a new one if there isn't one, and make sure it has permissions to access the themes. The API password will be generated when the app is created.
Once your config.yml file is ready, and saved in your working directory, you're ready to download the images.
In your terminal, run the command 'theme download'. You should see a progress bar appear, and if you have Finder or File Explorer open, then you'll see the files appearing there as they're downloaded.
Then, open ImageOptim and drag all the images into it to optimize them. There's something oddly satisfying about their drag-and-drop interface. Maybe it's just from optimizing images for years from the command line.
As it runs you'll see a little running total on the bottom of the total amount of space saved, and on each line the last column will have one or several names like "mozJPEG" or "Zopfli", which is the algorithm which resulted in the highest reduction for that image. Note: all algorithms it uses are lossless, so you don't have to worry about it affecting the quality of your images. It can take awhile since it is somewhat CPU intensive.
A note on image sizes: resizing some of these could drastically improve the reductions acheived, but only do this is if you're sure of all the places where the specific image is used. It's generally better to resize images at the theme level using the shopify img_url filter, in conjunction with html5 srcset attributes (shopify resizes and serves no bigger than needed, and srcset can only download the image needed depending on the device and pixel density of the screen displaying it).
Almost there! Once the images are optimized, we just need to upload them back up to the Shopify server to replace the old ones with the new ones. Run the command 'theme upload' to have themekit upload them automatically. It'll put them in the same theme that it pulled them from, so don't forget to make sure they actually end up in production (depending on your workflows this could be more complicated than just publishing the theme you've been working in).
Once the progress bar is completed and all the images are uploaded then you've successfully optimized all the theme asset images!
a note on image optimization for the web: there are two components to properly optimized images on a shopify site. There's optimizing the source, which is what we've done here - i.e. making the original file as small as possible and in the optimal format for its content, and then optimizing delivery, which is arguably the more important of the two. Optimizing the delivery of images is everything that happens between the image in a folder on a Shopify server, and it being downloaded to a user's device. This includes many layers, such as Liquid, where it can be cropped, reformatted, and sized to various dimensions, and distributed to the CDN with a versioned url, and the network and browser layer concerning how it's transmitted, how it's downloaded, and how it's displayed.
Thanks for reading!
get your theme id (edit code or preview theme, get theme ID from url or url param)
get your app password (make new private app if needed - instruction here)
b) download all images
>theme download - because we used "development" as the top level environment name, it'll default to the parameters we set up
and ignore all the file types except images *note must be run from the directory where config.yml is*
watch all the files appearing in your directory with wonder and awe.
c) optimize em! open image optim and drag and drop all the files into it. This can take awhile.
-I wish I knew more about optimizing GIF's. rather - I wish I knew an easy way to consistently optimizie GIFs, or a tool. Anybody?
d) now to upload
if you have the full theme downloaded (not *just* doing images, or other local dev work), you can ls > files.txt and then multi-select to add assets/ to before and then paste into a large theme upload command.