vuetifyjs / vuetify

šŸ‰ Vue Component Framework
https://vuetifyjs.com
MIT License
39.88k stars 6.96k forks source link

[Feature Request] How to improve lighthouse score with Vuetify #7265

Closed husayt closed 2 years ago

husayt commented 5 years ago

Problem to solve

We have a number of web sites with Vuetify and Nuxt. Vuetify works great for us, only concern is performance. As soon as we add vuetify Lighthouse score tumbles down. Most probably we don't follow best practices.

Here you can see lighthouse scores: https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.sozler.im https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fkoran.center

Proposed solution

Would be great to have a realistic example (not a hello world) with a few components which would score high on LightHouse and which can be a point of reference. Maybe you will discover, indeed there is a performance issue with adding Vuetify to your website and no realistic app would score high with Vuetify on LightHouse. That will allow to identify issues and resolve them.

Meanwhile, some tips and performance guidelines for Vuetify would be appreciated by everyone here.

Thanks

darylteo commented 5 years ago

Just adding to this.

We have just noticed that Vuetify's implementation of buttons don't conform to Material Design/Google Accessibility Guidelines as reported by Lighthouse.

Touch Targets have to be 48dp by 48dp, but the default v-btn are only 36x36 with a margin of 8px instead.

And here I am now trying not to strangle people asking me to overwrite the margins into paddings across the site. Which would be impossible as many of the buttons have customised margins depending on which component they're in.

johnleider commented 5 years ago

We will look into the lighthouse issues. As far as the touch target, I'm not really sure what we can do about the buttons.

KaelWD commented 5 years ago

I'm guessing it would have to be something like this: https://codepen.io/anon/pen/EqZMvZ

The reference implementation doesn't do it either: https://material-components.github.io/material-components-web-catalog/#/component/button

bengineer19 commented 4 years ago

Has there been any progress on strategies to improve Lighthouse score? If there are ways to use Vuetify which don't significantly negatively impact performance scores in Lighthouse then it would be really useful to have some examples or a short mention in the docs.

Otherwise, it seems virtually impossible to use Vuetify in any reasonable application without dragging a lighthouse score down from green into orange or red.

asennoussi commented 4 years ago

Any progress on this? I can't make it past 80 (Without tracking nor ads..)

johnleider commented 4 years ago

Are any of your implementations available that I can see?

asennoussi commented 4 years ago

Absolutely! I'll try to set it up today. But on the other hand, could you show us a site that is performing +90 on lighthouse using Vuetify?

bengineer19 commented 4 years ago

Just running vue create my-app then vue add vuetify as in the quickstart guide results in a demo page which when built has weirdly high FCP and TTI.

asennoussi commented 4 years ago

@johnleider, I could reproduce the performance issues with the quickstart as @bengineer19 mentioned

husayt commented 4 years ago

That quickstart demo is probably the best place to start from. Then we can try to look into problems with real websites, like for instance https://www.sozler.im/ or https://koran.center. Google is heavily penalising these websites due to performance issues.

bengineer19 commented 4 years ago

Yep. I'm currently working on a new site using Vuetify which will replace a legacy site with millions of users anually. Our biggest worry about changeover is that our Google rankings will take a dive because of the lighthouse hit incurred by Vuetify. So am very happy to help out with this if pointers are available!

tschut commented 4 years ago

I'm the developer for wammes-gifts.nl, and according to https://developers.google.com/speed/pagespeed/insights/ the score for desktop is fine, but on mobile it's not.

@johnleider if it helps I can probably get you access to the repo for that, at least temporary?

micardona96 commented 4 years ago

the performance scoring is only affected in the test by running on mobile,

image

How could I solve this, I emphasize that it is just the simple sample app, with:

>> vue add vuetify

https://api-springboard.web.app/#/

syskin commented 4 years ago

After some test with vuetify on a nuxtjs application, it seems to be that bad performances come from default icons load and fonts load.

If you try to remove default values, and import your own icons and fonts, your app you can easily get 95+ lighthouse score.

tajnymag commented 4 years ago

@syskin Could you please share with us, what combination of fonts/icons fares well on Lighthouse? I've tried self hosting several roboto and icon fonts and it didn't lead to much better results.

DRoet commented 4 years ago

I think its also good to note that the lighthouse score heavily depends on the specs of the machine its being run on, for example on a slower machine I might get around a ~80, while on a fast machine I consistently get 96-97 using the same website

asennoussi commented 4 years ago

@DRoet, That's for field Data, not lab data. Lab data should be consistent as it's simulating the same shitty device for all websites.

syskin commented 4 years ago

@syskin Could you please share with us, what combination of fonts/icons fares well on Lighthouse? I've tried self hosting several roboto and icon fonts and it didn't lead to much better results.

I follow the doc recommendation for production deployment, I import mdi/js (https://vuetifyjs.com/fr-FR/customization/icons/#installer-les-icones-material-design-js-svg) and I override @fontface property in CSS file as it is said.

But I used the nuxtjs/vuetify module, so I don't know how you can override that properties in a classic vuetify app.

yohane55 commented 4 years ago

I too have 38% performance for my site. But the official vuetify site also have 41%.

Screen Shot 2020-06-15 at 7 59 18 PM
Radiergummi commented 4 years ago

To chime in here; I'm working on a new greenfield project and settled on Nuxt.js, Vuetify and TypeScript. We have Lighthouse results around 80 on desktop and 36 on mobile.
What I found to be the hardest thing during development was creating a production setup. Almost all resources online seem to assume some kind of prototype or dev environment, not an actual performance-optimized production application. The Vuetify documentation doesn't help too much here, either: There's no section dedicated to production setup or optimization. Getting icons right, for example, requires digging deep into the docs until you find the relevant snippet:

Use the SVG paths as designated in @mdi/js. This is the recommended installation when optimizing your application for production. You ONLY need to include this if you plan on using more than the default icons.

I understand this makes kind of sense given that not every application requires icons outside of Vuetify components, but it's really not obvious until you actively search for solutions to performance problems.
Is there any guide for production setups somewhere? Could we, as a community, get together and create one, to be featured in the Vuetify documentation?

husayt commented 4 years ago

This is the single biggest problem with Vuetify and I still found no good solution to this. My websites are being heavily penalised by search engines for that, to the point that I have already migrated some of them away and some are in process. Currently my recomendation is unfortunately, if SEF&SEO are of any concern Vuetify will not be the right choice. It's a shame, it has so many good features, but here we are.

maartenvn commented 4 years ago

You can easily remove unused CSS from @mdi/font by using PurgeCSS. I am using this configuration with Vuetify and it stripped around 200kbs of the CSS bundle. Only the mdi icons used in the application are included in the actual bundle.

npm i @fullhuman/postcss-purgecss @fullhuman/vue-cli-plugin-purgecss

postcss.config.js

const purgeCSS = require("@fullhuman/postcss-purgecss");

const PRODUCTION = process.env.NODE_ENV === "production";

module.exports = {
    plugins: [
        PRODUCTION &&
            purgeCSS({
                content: [
                    `./public/**/*.html`,
                    `./src/**/*.vue`,
                    `./node_modules/vuetify/src/**/*.ts`,
                    `./node_modules/vuetify/dist/vuetify.css`
                ],
                safelist: [
                    /-(leave|enter|appear)(|-(to|from|active))$/,
                    /^(?!(|.*?:)cursor-move).+-move$/,
                    /^router-link(|-exact)-active$/,
                    /data-v-.*/
                ]
            })
    ]
};

You could even remove the ./node_modules/vuetify/dist/vuetify.css line if you whitelist the CSS classes that are injected at runtime and shave it down by almost 400kb in total (in my case).

Radiergummi commented 4 years ago

@maartenvn Nice! I'm absolutely going to steal this snippet šŸ˜‰

On a serious note, though, that's exactly what I was talking about. Maybe we can collect stuff like this into a comprehensive guide for Vuetify production setups?

tajnymag commented 4 years ago

@Radiergummi Why stop there? The snippet of @maartenvn could even be included in the official vuetify vue-cli plugin, thus everyone would get this optimization by default.

asennoussi commented 4 years ago

PurgeCSS never worked out for me. But I will test this snippet hoping that it's working today.

maartenvn commented 4 years ago

I ended up switching to @mdi/js anyways, because the full webfont is still included with @mdi/font.

Unfortunately performance is still terrible.

image

husayt commented 4 years ago

If you look in detail at LighouseLogs for what is causing performance issues, it's not css. https://developers.google.com/speed/pagespeed/insights/?url=https%3A%2F%2Fwww.sozler.im

Purgecss is good step, but not the solution to the problem.

Velikolay commented 3 years ago

I'm also experiencing major performance issues on mobile, especially mid / low tier devices. Loading and changing between pages is painfully slow. Understandably the Lighthouse / Page Insights score is also low - can't make it past 50 on the google test for a static home page with very little content on it. It was my intention to use vuetify for the app's blog in order to reuse some of the layout and individual components, but that's unthinkable with this score and ux.

It's a the javascript evaluation and execution that's slow, the main-thread is busy for tool long. Did some profiling on a x4 slowdown to replicate mobile.

Static page with a header / footer and minimal content: 2s execution

profiler-home

Larger dynamic page with more components and API data: 5s execution

profiler-search

After optimising everything there is, i'm stuck with these numbers. Tips are welcome.

P.S. I can confirm @husayt 's observation that css is not the main issue, yet it's a huge file and it can be an issue on a slow network. I tested the app without css (yes, ugly unstyled page) => was still just as slow.

hagemann commented 3 years ago

But I used the nuxtjs/vuetify module, so I don't know how you can override that properties in a classic vuetify app.

To those who are also using nuxtjs/vuetify and are not making use of Vuetify fonts or icons, set defaultAssets to false. This helped me get the scores up from 42/91 (mobile/desktop) to 75/98.

I retained other render-blocking resources like polyfill and FontAwesome Kit which could give another boost if removed, but Iā€™m happy enough for the time being. With that said, I think Vuetify is quite usable for production.

Source: https://github.com/nuxt-community/vuetify-module#defaultassets

KaelWD commented 3 years ago

You can eliminate the polyfills too with modern builds: https://nuxtjs.org/docs/2.x/configuration-glossary/configuration-modern/

maartenvn commented 3 years ago

For those using Nuxt.JS in SSR mode, there is a way to drastically improve the lighthouse score using the package: @luxdamore/nuxt-prune-html

This package will strip unnecessary Javascript when a bot User-Agent is detected. Since the bad lighthouse score is mostly coming from the First Contentful Paint, this will drasticly improve the score.

Note: this will not fix the performance issues with the framework itself for regular users. The main benefit here is that the search engine ranking will not be penalized due to bad performance.

This is my performance on mobile, coming from a 34/100 score before:

image

asennoussi commented 3 years ago

For those using Nuxt.JS in SSR mode, there is a way to drastically improve the lighthouse score using the package: @luxdamore/nuxt-prune-html

This package will strip unnecessary Javascript when a bot User-Agent is detected. Since the bad lighthouse score is mostly coming from the First Contentful Paint, this will drasticly improve the score.

Note: this will not fix the performance issues with the framework itself for regular users. The main benefit here is that the search engine ranking will not be penalized due to bad performance.

This is my performance on mobile, coming from a 34/100 score before:

image

WRONG! Search Engines consider the field data i.e what users experience with your site. IF you're using nuxt-prune, you're fooling only yourself or the manager who asked for a better performance. The speed report on search console and CrUX are the only source of truth about the signals search engines consider as ranking factor.

maartenvn commented 3 years ago

WRONG! Search Engines consider the field data i.e what users experience with your site. IF you're using nuxt-prune, you're fooling only yourself or the manager who asked for a better performance. The speed report on search console and CrUX are the only source of truth about the signals search engines consider as ranking factor.

I wasn't aware of this. Do you have a source on that? Thanks

KaelWD commented 3 years ago

https://developers.google.com/search/docs/advanced/guidelines/cloaking

asennoussi commented 3 years ago

https://blog.searchmetrics.com/us/core-web-vitals/

asennoussi commented 3 years ago

https://developers.google.com/search/docs/advanced/guidelines/cloaking

This is unrelated because the content from SSR is likely the same as the one with JS, only there is no hydration

husayt commented 3 years ago

Anyone here claiming to have fantastic lighthouse scores with Vuetify, please, also provide a link. Without seeing the complexity of website lighthouse score alone, even if it is achieved doesn't mean much.

asennoussi commented 3 years ago

No need to provide a link. Lab data is bullshit. Talk to me field data ;) image

asennoussi commented 3 years ago

hehehehe I didn't provide any screenshot before but whatever makes you sleep at night :)

husayt commented 3 years ago

hehehehe I didn't provide any screenshot before but whatever makes you sleep at night :)

Sorry, saw your name under previous screenshot. Didn't realise that you were replying.

asennoussi commented 3 years ago

But hey, Vuetify does come with some heavy ass components that can be optimized heavily. For example the Skeletons, they're using the main thread to animate the loaders which is crazily expensive. The right way is to use GPU. I tweeted about this in the past but I don't know if it's been taken care of. https://twitter.com/aysennoussi/status/1290176046696816640

Tofandel commented 3 years ago

I got my score at 80 using prerendering, some preloading and lazy loading. But yeah it looks like most of the performance issue (The last 20%) comes down from the core and could be see a few optimizations to get the performance we deserve :100:

Mostly the script evalutation takes ~500ms

johnleider commented 3 years ago

I tweeted about this in the past but I don't know if it's been taken care of. twitter.com/aysennoussi/status/1290176046696816640

I did not see this, we'll look into it. Thank you

johnleider commented 3 years ago

Working with the Vuetify preset, these are my results for local and web.dev:

deployed-lighthouse-incognito deployed-lighthouse-webdev

Here is the link to try out yourself: https://my-app-pied-phi.vercel.app

In a nutshell, the performance is drastically different. Not sure how to reconcile this.

asennoussi commented 3 years ago

That's actually consistent. Because all the measurements are tightly related to the FCP. The higher the FCP, the higher everything else because everything else starts calculating after FCP, so if FCP takes 5 secs, everything else will be +5s.

I'm saying it's consistent because the difference between TTI or Speed index from the FCP is closely the same on both web.dev and Lighthouse.

Now why does it have 5s FCP? Lots of reasons but mainly related to the server, not to Vuetify.

mcoolidge commented 3 years ago

Anyone here claiming to have fantastic lighthouse scores with Vuetify, please, also provide a link. Without seeing the complexity of website lighthouse score alone, even if it is achieved doesn't mean much.

Very simple example here: https://www.orbitalhealth.co/

Didn't do much to optimize yet.

image

maartenvn commented 3 years ago

Didn't do much to optimize yet.

image

PageSpeed Insights says otherwise:

image

https://developers.google.com/speed/pagespeed/insights/?hl=en&url=https%3A%2F%2Fwww.orbitalhealth.co%2FPlatform


At VueConf US John Leider said Vuetify v3 will have major performance improvements. So it looks like the future is bright in terms of performance :slightly_smiling_face:

mcoolidge commented 3 years ago

Thx for the heads up. Love how easy and consistent lighthouse tools are šŸ˜‰

ManasMadrecha commented 3 years ago

I use Nuxt + Content + Tailwind + Vuetify. I was able to improve the score for Mobile to 87 and for Desktop to 94. šŸ˜ƒ

image

image

Things I did

W.r.t. Vuetify

  1. Tailwind has the great JIT feature. So, I can use its utility classes like margin, padding, colors, etc endlessly. So I don't need Vuetify's colors and all. I only use Vuetify for the javascript stuff. Whenever I need to color some button or icon, I can simply use tw-text-blue-700, etc. So, I have disabled all the colors and utility classes of Vuetify. This itself had the biggest improvement with the view-source page reducing from 30k lines to half.
$color-pack: false 
// https://vuetifyjs.com/en/styles/colors/#sass-color-pack

@import '~vuetify/src/styles/styles.sass'

@each $name, $value in $utilities  
  $utilities: map-merge($utilities, ($name: false))
  1. Next, I have set the defaultAssets to false inside the Nuxt Vuetify module.

  2. Next, instead of using cdn's css mdi fonts, I have installed mdi/js, so that I can import only a couple of dozens font I will ever use either in .vue files or in Content's markdown files. Removing the cdn css will save you at least 0.15 seconds.

  3. And, of course treeshake has been set to true in Nuxt Vuetify module.

Other optimizations

  1. Google Fonts:
// nuxtconfig.js --> inside the head object

    link: [
      {
        rel: "preconnect",
        href: "https://fonts.gstatic.com",
        crossorigin: ""
      },
    ]
  },
// layouts folder --> default.vue --> head object which returns (along with meta, etc.) the following:

      link: [
        // https://csswizardry.com/2020/05/the-fastest-google-fonts/
        {
          rel: "preload",
          as: "style",
          href:
            "https://fonts.googleapis.com/css2?family=Vesper+Libre:wght@400;500;700&family=Open+Sans:wght@300;400;600;700&display=swap"
        },
        {
          rel: "stylesheet",
          href:
            "https://fonts.googleapis.com/css2?family=Vesper+Libre:wght@400;500;700&family=Open+Sans:wght@300;400;600;700&display=swap",
          media: "print",
          onload: "this.media='all'"
        }
  1. Also, I have enabled modern build in Nuxt with the babel presets changed (I don't care about older browsers) in nuxtconfig.js file. This again saved me half a second. Of course, this has nothing to do with Vuetify, but it improves lighthouse house drastically.
package.json
  "scripts": {
    "dev": "nuxt",
    "generate": "nuxt generate --modern",
// nuxtconfig.js
  // Build Configuration: https://go.nuxtjs.dev/config-build
  build: {
    // extractCSS: true,

    // https://github.com/nuxt/nuxt.js/issues/4552#issuecomment-761786540
    // https://philipwalton.com/articles/deploying-es2015-code-in-production-today/
    // https://web.dev/codelab-serve-modern-code/
    babel: {
      presets({ isClient }, preset) {
        if (isClient) {
          preset[1].targets = {
            browsers: [
              'Chrome >= 60',
              'Safari >= 10.1',
              'iOS >= 10.3',
              'Firefox >= 54',
              'Edge >= 15',
            ]
          }
        }
        return [preset]
      }
    },
  },

https://github.com/jainism-portal/jainaagam/blob/b10a7efd879cebb7d28bcce416446f2f4a8a9113/nuxt.config.js#L306-L336

Pending issues with Vuetify

  1. I use a sidebar menu with v-navigation-drawer, which is toggleable from a button placed on v-app-bar. But it causes huge Cumulative Layout Shift on Desktop because it opens up later. Maybe it is because of this:

While the $vuetify object supports SSR (Server-Side Rendering) including platforms such as NUXT, the breakpoint service detects the height and width values as 0. This sets the initial breakpoint size to xs and in some cases can cause the layout to snap in place when the client side is hydrated in NUXT.

However, this is not an issue on Mobile, and for Desktop, other parameters can compensate for this one issue.

  1. Also, the v-breadcrumbs again cause huge CLS.

  2. Vuetify still loads so much CSS, even for the components I haven't used anywhere like v-alert, ripple etc. So, it again can seek inspiration from Tailwind's JIT.

But compared to when I first used Vuetify with no changes made, this is remarkable improvement in score. So, no major complaints against this amazing library. šŸ’›

johnleider commented 3 years ago

@ManasMadrecha If you'd be interested in helping us beef up our performance documentation, please reach out to me in Discord community, https://community.vuetifyjs.com.