Vue.Js Mobile Desktop Optimized Images

Ethan Ozelius
The Startup
Published in
6 min readJul 14, 2020

Mobile devices and internet speeds have come a long way. Gone are the days of one wifi bar and a dream, praying the 99 cent 3.1K iTunes song you just purchased for your slick new 8G iPod mini will download in under an hour. If at all.

Nowadays web developers build expensive beautiful web apps with high-resolution professional photography. But even with how far mobile devices have come, high-quality images taken with a decent phone camera can easily reach 5–6 MB, which will not only slow mobile image rendering to a crawl but for many desktop web experiences, could be way overkill.

Optimizing images for desktop and mobile devices requires just a basic understanding of photoshop, some JS foo, and a basic understanding of how images are deployed with your Front End Framework. But the payoff of optimized lighting quick high-quality images will be well worth the effort.

For this tutorial, I’ll use the open-source image editing program Gimp version 2.10, and Vue.js my favourite Front End framework. Let's start with this high-quality image of a jumbled workbench taken with my OnePlus 5 phone, which has a 16MP camera.

Original 5.6MB Image — Cocora Valley, Quindío Colombia.

There’s a high degree of detail in this photo, and I want to preserve each leaf, no matter what device I’m using. This photo measures 4608x3456 pixels and weighs in at a whopping 5.6MB.

If I was building a professional photography website, I might leave this image in its current format to really wow website visitors. But for most scenarios, this image could slow performance and rendering, even on a powerful desktop computer with a fast wifi connection. So for this tutorial, I’m going to optimize this image for desktop and mobile by scaling the size down a bit.

You’ll have to play around with each image a bit to achieve the balance of image quality and rendering speed that is right for your application, but in my experience I’ve found that images in the neighborhood of 1200–1600 pixels wide will look amazing on desktop devices. For mobile, I usually go for about 400–600 pixels wide. Once you get the hang of it, you’ll be able to dial in the exact proportions that are right for you.

Before we get to image optimization, let’s organize our Vue app images directory. Create a directory structure that makes sense for your app, my images directory looks like this

// my_vue_app/src/assets/images/
|__ desktop/
|__ mobile/

Note: Photo editing and coding are similar in that it’s a good idea to make a copy that you can fall back on if things go south.

To optimize our images, open the original image in Gimp. To Scale an image in Gimp, go to Tools > Transform Tools > Scale

Once the Scale tool is active, click the image, and a dialog box will appear for you to set the new width and height. I always scale the height proportionally to the width, this can be done automatically with Gimp, but selecting the chain link icon in the scaling dialog box. Set the image width to 1600px, and the height will update automatically.

Once the image has been scaled to our desktop dimensions of 1600 x 1200 pixels, copy the image by holding Cmd + C, or Shift + C on Windows and Linux machines.

Next create a new Gimp image file with File > New. Set the width and height on the new Gimp file to 1600 x 1200 pixels and click OK. Once the new Gimp file loads, simple paste your scaled image from clipboard into the new Gimp image with Cmd + V or Shift + V.

Optimizing for mobile devices is much the same process, with a small caveat. Our mobile images will be portrait not landscape, so we need to select only a section of our original image that will look best on mobile devices.

To select a portrait section of our original image, go to Gimp Tools > Selection Tools > Rectangular Select. Once the rectangular select tool is active, drag across the original image until you find a portrait selection that looks good to you. Once you’ve got it, scale the selection to 500 x 750px, copy the scaled selection, create a new 500 x 750px Gimp image and paste the selection into the new file.

Finally we need to export (not save) our optimized images into our Vue app. In Gimp go to File > Export As, and select the mobile and desktop image directory where you would like your new images to be exported to. Once you have selected your location, another Gimp dialog box will open making sure you are alright with the exporting settings. Note: I’ve always had good luck with the default settings, and was always too impatient to get back to coding to dive too deeply into what each of these settings do, but if you’re curious, dive right in.

With our optimized images exported to their proper directories, you should have an images directory like this.

// my_vue_app/src/assets/images/
|__ desktop/cocora_valley.jpg [ 981 KiB ]
|__ mobile/cocora_valley.jpg [ 376 KiB ]

With our optimized images exported to their proper directories, it’s time to dive into the code to serve one of these two images based on screen size.

We will create a simple util function called isMobile.js that will return true if the screen width is less than 500 pixel, while this solution won’t cover every single edge case, it’s good enough for our purposes.

Next create a <Picture /> component

The only interesting bit about this component is the <img :src="require(getOptimizedImage)", which dynamically loads an image from either the large or small directory, based on the isMobile() .

Let’s spark up our app to see our work in action!

Gif of mobile and desktop optimized images in vue app.

A quick note about overall build size and how assets are deployed.

When you build your app webpack will likely give you several warnings that your desktop images are larger than the suggested maximum asset size of 244 KiB.

asset size limit: The following asset(s) exceed the recommended size limit (244 KiB).
This can impact web performance.
Assets:
assets/image/desktop/cocora_valley.jpg (981 KiB)
assets/image/mobile/cocora_valley.jpg (376 KiB)

Relax webpack, we’re pros here.

Obviously these high quality images will significantly bump up our production builds folder’s footprint, but a larger build folder, doesn’t necessarily equate to slower load times. To understand this we need to understand how a deployed app built with Vue CLI is structured (create-react-app is structured in a similar fashion).

When we run yarn build, a dist folder is created with the following structure, containing everything a user needs to interact with our website, images, styles, our Front End code and dependencies.

A dist folder built with Vue CLI will look like this:

drwxr-xr-x   4 ethan  staff   128B Jul 12 14:22 css/
-rw-r--r-- 1 ethan staff 4.2K Jul 12 14:22 favicon.ico
drwxr-xr-x 29 ethan staff 928B Jul 12 14:22 img/
-rw-r--r-- 1 ethan staff 857B Jul 12 14:22 index.html
drwxr-xr-x 8 ethan staff 256B Jul 12 14:22 js/

When this directory is deployed to a server, and a browser visits our site, the index.html file is returned to the browser, which contains a <script> tag that loads our app.bundle.js. Once that index.html and app script tag render in the browser, Vue takes over and brings all it’s Vue magic!

Only when our <Picture /> component is rendered, will the <img :src="require(getOptimizedImage)" initiate a network request for our image.

As opposed to everything, styles, images and JS code all being bundled into one single massive app.bundle.js file. Which is how some Front End build tools used to function. *a-hem* not naming names, I’m sure it made a lot of sense at the time.

This means that I can confidently build mobile and desktop images into the same build and not worry that mobile users will be bogged down by unnecessarily loading desktop images and vice versa.

Enjoy!

--

--

Ethan Ozelius
The Startup

Just a drifting computer hacker trying to get some sunshine.