Compressing Images With Vite and Vsharp

Images are usually the biggest cause of slow webpages. This article tackles how we can improve our page speeds in Nuxt by compressing images.

Michael Thiessen
Nuxt 3

Mastering Nuxt 3 course is here!

Get notified when we release new tutorials, lessons, and other expert Nuxt content.

Click here to view the Nuxt 3 course

Images are one of the biggest causes of slow webpages.

We have a bunch of strategies for dealing with this, but the most basic one is to make sure each and every image in your app is compressed as much as possible.

Fortunately for us, setting up Nuxt to automatically compress our images only takes a few minutes.

Images in Nuxt

Let’s say we have an app with a bunch of images in our /assets folder.

Because these images aren’t in /public, they won’t be automatically included in the final build of our app. So we need to make sure to import them where we need them.

We’ll use an img tag in our template like this:

<template>
  <!-- Somewhere in our template -->  
    <img
      :src="screen3"
      class="w-full rounded-lg shadow-lg border-2 border-slate-200"
    />
  <!-- ... -->
</template>

And then make sure to import the images that we need, just like we’d import a method or component:

// Import all the images we need
import screen1 from '~/assets/images/screen1.png';
import screen2 from '~/assets/images/screen2.png';
import screen3 from '~/assets/images/screen3.png';
import screen4 from '~/assets/images/screen4.png';
import screen5 from '~/assets/images/screen5.png';

But these images will be included into our app as-is, without any compression.

This is a problem.

What we’d like is for any image that gets included to be automatically optimized as part of the build process. That way we know for sure that all of our images are as small as they can be, and won’t slow down our page load times too much.

Installing and configuring vsharp

There are a few different Vite plugins for compressing images, but for this tutorial we’ll use [vsharp](https://github.com/jw-12138/vite-plugin-vsharp). I haven’t done an extensive side-by-side comparison of plugins, but this one has worked well for me.

To install, run pnpm add -D vite-plugin-vsharp.

To configure it, we need to update our nuxt.config.ts file. We need to add it to the plugins field in our vite section. If you don’t have that yet, you can add it now.

Your nuxt.config.ts will end up looking something like this:

import vsharp from 'vite-plugin-vsharp';

export default defineNuxtConfig({
    // 👇 Add vsharp to the vite plugins
  vite: {
    plugins: [vsharp()],
  },

  // The rest of your Nuxt config
  runtimeConfig: {
    stripeSecret: '',
    stripeWebhookSecret: '',
    public: {
      stripeKey: '',
    },
  },
  nitro: {
    prerender: {
      routes: ['/landing'],
    },
  },
  modules: [
    '@nuxtjs/tailwindcss',
    '@vueuse/nuxt',
    '@nuxtjs/supabase',
    '@pinia/nuxt',
  ],
});

That’s it!

Now, when you run pnpm build (or npx nuxi build) you’ll see that it’s compressing every single image that’s used in your app. It will also show you exactly how much it’s compressing each image, and how much smaller your app bundle will be.

That’s a big win for a small config change!

Michael Thiessen
Michael is a passionate full time Vue.js and Nuxt.js educator. His weekly newsletter is sent to over 11,000 Vue developers, and he has written over a hundred articles for his blog and VueSchool.

Follow MasteringNuxt on