How to preload CSS in Vue

Hey guys,

I’m looking for a way to make my Vue SPA load faster. Currently, my Lighthouse performance score is just 20/100 and it points to me a 6.24s saving potential (!) by “Preloading key requests” => which maps to a CSS chunk. My app has a single global.css file with ~1.000 lines (no animations, no SCSS… just simple classes) + scoped CSS inside components.

Can someone guide me on what to do (probably a Webpack config)?

Thanks!

1 Like

Just adding: This is my current Webpack config (vue.config.js)

const webpack = require("webpack");

module.exports = {
  configureWebpack: {
    plugins: [new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)],
    optimization: {
      runtimeChunk: "single",
      splitChunks: {
        chunks: "all",
        maxInitialRequests: Infinity,
        minSize: 0,
        maxSize: 200000,
        cacheGroups: {
          vendor: {
            test: /[\\/]node_modules[\\/]/,
            name(module) {
              const packageName = module.context.match(
                /[\\/]node_modules[\\/](.*?)([\\/]|$)/
              )[1];
              return `npm.${packageName.replace("@", "")}`;
            }
          }
        }
      }
    }
  },
  chainWebpack: config => {
    config.module
      .rule("i18n")
      .resourceQuery(/blockType=i18n/)
      .type("javascript/auto")
      .use("i18n")
      .loader("@kazupon/vue-i18n-loader")
      .end();
    config.performance.maxEntrypointSize(400000).maxAssetSize(400000);
  }
};

Can you post your lighthouse results? It’ll be easier to advise if we can see the whole report. Also, did you run the report on your production build?

Hey James, thanks for the quick reply.

Yes, I ran the report on my production build.
Here’s a print of the result:

I’m having the same issue. The Chrome Lighthouse Audit says that the CSS chunks made by Vue should be preloaded with < link rel=‘preload’ >

I did some digging, and it seems that Vue adds these chunks as ‘prefetch’, while Lighthouse suggests them to be added as ‘preload’. I have no idea on who is right, I just wanted to shed more light on the issue.

I’m using Vue Router. The first CSS (meta.790fcc77.css) belongs the the current route (Meta). I guess second CSS (meta~mwl~rotation.d2dd59bb.css) is used by all of my three routes (Meta, MWL, Rotation).

Hey Patrick, having the same issue as yourself as well. Just to note, I found that doing the Lighthouse audit inside chrome dev tools provides pretty different results with regards to your performance score. However what is common in both is the ‘potential savings’ of several seconds.

I too would love for someone to shed some light on this. I did play around a little with the Prefetch configuration described here:
https://cli.vuejs.org/guide/html-and-static-assets.html

I thought by disabling prefetch, preload would be used by default, but this actually made my scores worse, so I went back to what I had.

What works for me is to disable prefetch, then preload allChunks.
Add this in your vue.config.js:

  chainWebpack: (config) => {

    /* 
       Disable (or customize) prefetch, see:
       https://cli.vuejs.org/guide/html-and-static-assets.html#prefetch
    */
    config.plugins.delete('prefetch')

    /* 
       Configure preload to load all chunks
       NOTE: use `allChunks` instead of `all` (deprecated)
    */
    config.plugin('preload').tap((options) => {
      options[0].include = 'allChunks'
      return options
    })
  },

}

Thank you MacMaru for sharing, that works.

But I’m getting these warning now:

The resource myresource.9c35263f.js was preloaded using link preload but not used within a few seconds from the window’s load event. Please make sure it has an appropriate as value and it is preloaded intentionally.

I think I have solved this issue without plugins and additional configurations

// Inside router/index.js

// The main page that is loading when user open app, load it without creating chunks and lazy loading:

import Home from “…/views/Home.vue”;
component: Home,

// For the rest of pages use lazy loading
For pages that should be loaded later I used lazy loader:

component: () =>
  import(/* webpackChunkName: "create" */ "../views/Create.vue"),

That added around ~5-10 performance points for me

1 Like