vuetify-module icon indicating copy to clipboard operation
vuetify-module copied to clipboard

Lighthouse performance on create-nuxt-app w/ vuetify

Open andrewspy opened this issue 5 years ago • 21 comments

Module version v1.11.2

Describe the bug Less than ideal score on lighthouse (mobile performance).

To Reproduce https://github.com/andrewspy/nuxt-app

Steps to reproduce the behavior:

  1. yarn global add create-nuxt-app
  2. create-nuxt-app nuxt-app
  3. yarn build
  4. yarn start

Expected behavior Expect a better "green" score on lighthouse (mobile performance). First paint of 4.3s for an SSR seems slow.

Screenshots lighthouse

Additional context It's not a bug per se, but out of the box performance should be better, am I missing something?

andrewspy avatar May 13 '20 08:05 andrewspy

Lighthouse by default applies 4x throttling to simulate a 3G/ low quality 4G connection. So I think unless you really optimize your site you'll see bad scores there.

A better test is PageSpeed Insights. It should be noted that when I did npx create-nuxt-app and went straight to PageSpeed I got 79 on mobile and 96 on desktop.

Adding extractCSS: true to build{} as well as using the latest version of vuetify got me up to 90 on mobile and 98 on desktop

image image

simeon9696 avatar May 18 '20 15:05 simeon9696

@simeon9696 Thanks for sharing your result. I am aware that lighthouse apply throttling to simulate mobile scenario, and I am testing create-nuxt-app out of the box on local machines as a standard baseline to minimize other factors that may affect the audit (such as hosting/network etc).

I have also added extractCSS: true and update vuetify to the latest version, but the result seems to be no different. I'm surprised to see that your result performs so much better on netlify w/ PageSpeed Insight, would it be possible to share your lighthouse mobile performance result on local machine as well?

My point is if the baseline create-nuxt-app (with vuetify) can't achieve a "green" score on local machine, there is no way for an app to perform better when building on top of it.

Heard Vue3 does improve SSR performance, will have to see how it performs when (nuxt+vuetify) is ready for Vue3.

andrewspy avatar May 19 '20 05:05 andrewspy

@simeon9696 Just for a quick update, I have removed @nuxtjs/vuetify for testing purpose, and manage to score a 98-100 on lighthouse.

  buildModules: [
    // Doc: https://github.com/nuxt-community/eslint-module
    '@nuxtjs/eslint-module'
    // '@nuxtjs/vuetify'
  ],

create-nuxt-wo-vuetify

Obviously, this is only meant for testing purposes, but it seems there is room for improvement in vuetify.

andrewspy avatar May 19 '20 06:05 andrewspy

Lighthouse mobile score as requested w/ simulated throttling

image

And applied throttling: image

I think it's okay, and you're right if you start building your app on this baseline then it can only go down. I'm not sure how you would even begin to fix this. If the project you're looking to build is small and doesn't require a whole lot of elements I'd suggest Vuesax

simeon9696 avatar May 20 '20 02:05 simeon9696

@simeon9696 Thanks, I'll have a look at Vuesax. Shall keep this open and do a lighthouse test when vuetify-module support vue3.

andrewspy avatar May 20 '20 13:05 andrewspy

Hi,

i have the same issue. I wont to work with nuxt and vuetify. But the performance is not as good as i expected. I hosted a new project on my server. I configured the IIS as reverse proxy to localhost:3040. If I am hosting nuxt without vuetify i got results Mobile 98 and Desktop 100. With vuetify i implemented the following steps:

My installation Config was: 2020-05-31 11_41_30-nuxt config js - _uebungen_ - Visual Studio Code

If I Build the project without any config i got one big vendor: 2020-05-31 11_43_18-nuxt config js - _uebungen_ - Visual Studio Code

Hosted on my server - here are the results: Desktop 2020-05-31 11_49_44-PageSpeed Insights Mobile 2020-05-31 11_54_32-PageSpeed Insights

I also tried to implement the extractCSS: 2020-05-31 11_46_20-● nuxt config js - _uebungen_ - Visual Studio Code

Now if i am building the project the vendor is 50% smaler: 2020-05-31 11_49_05-nuxt config js - _uebungen_ - Visual Studio Code

If I do that - the sults are much worse than before: Desktop: 2020-05-31 11_54_40-PageSpeed Insights Mobile: 2020-05-31 11_50_07-PageSpeed Insights

After a long reseach session i found the following article: https://www.davidroyer.me/blog/nuxtify-project/

There someone reachted my goal to improve the score to nearly 100 I downloaded his solution. But he implemented the vuetify project with the vuetify-loader and not as processed in the documentation.

Or is the solution of the nuxtify-project the correct one? I also tried to implement the https://purgecss.com/. But if i do that the whole layout is broken. This feature dont know which vuetify css is used.

So my question: If I got it right, will you work on a solution to increase the performance a bit? Or do I have to look for a better solution myself? I want to use vuetify because I'm starting a very large project and the performance has to be right from the start.

Another prolmen is the TTFB: image

I know that the ssr function can downgrade the response that it will take a little longer but I only have this response time since I started the nuxt.js project with vuetify. Do you have any ideo or does i have to open another issue?

Many thanks for the help

lg chriss

HoehensteigerGames avatar May 31 '20 12:05 HoehensteigerGames

@HoehensteigerGames I have been through the same process as you did, and it seems the bottleneck is in vuetify v2. Also, you can't use https://www.davidroyer.me/blog/nuxtify-project/ as a reference as it uses vuetify v1.5 which is outdated and very different from v2.

Personally, I am investigating on https://quasar.dev/ for the SSR performance as it is important for my use case, but I missed the whole nuxt/vuetify ecosystem. Hopefully, vuetify team can look into this and address it in upcoming releases.

Also, the issue is also mentioned in vuetifyjs/vuetify#7265.

andrewspy avatar May 31 '20 21:05 andrewspy

Thanks for the suggestion. yesterday i spent the whole day figuring out what the problem is. in short I have switched off the defaultAssets to remove the mdi fonts (material-design-icons). Then I implemented the roboto font type with webfontloader and now I have my desired result.

That is the Config: image

image image

these are my results: Desktop: (98 - 100) image

Mobile: (90 - 95) image

Now the only differnece is that i import my Icons manually with @mdi/js.

HoehensteigerGames avatar Jun 01 '20 06:06 HoehensteigerGames

@HoehensteigerGames

I wrote a vue-template-compiler module so it can inject the svg path directly in the compiled template, so in 95% of use cases no need to import it directly. (As long as the 'mdi-*****' string is in the template it works.)

Might worth a try:

https://github.com/mathe42/vuetify-icon-injector

Install:

yarn add https://github.com/mathe42/vuetify-icon-injector

nuxt.config.js:

const vueLoaderOptions = {
  compilerOptions: {
    modules: [
      require('vuetify-icon-injector').getIconInjector()
    ]
  }
}

module.exports = {
  build: {
    loaders: {
      vue: vueLoaderOptions
    }
  }
}

⚠️ Note: This changes the output of the vue-template-compiler. So it can break your project!

mathe42 avatar Jun 01 '20 07:06 mathe42

@HoehensteigerGames

I wrote a vue-template-compiler module so it can inject the svg path directly in the compiled template, so in 95% of use cases no need to import it directly. (As long as the 'mdi-*****' string is in the template it works.)

Might worth a try:

https://github.com/mathe42/vuetify-icon-injector

Install:

yarn add https://github.com/mathe42/vuetify-icon-injector

nuxt.config.js:

const vueLoaderOptions = {
  compilerOptions: {
    modules: [
      require('vuetify-icon-injector').getIconInjector()
    ]
  }
}

module.exports = {
  build: {
    loaders: {
      vue: vueLoaderOptions
    }
  }
}

⚠️ Note: This changes the output of the vue-template-compiler. So it can break your project!

Can we use npm install?

simeon9696 avatar Jun 05 '20 01:06 simeon9696

Yes npm i https://github.com/mathe42/vuetify-icon-injector

mathe42 avatar Jun 05 '20 05:06 mathe42

Thanks for the suggestion. yesterday i spent the whole day figuring out what the problem is. in short I have switched off the defaultAssets to remove the mdi fonts (material-design-icons). Then I implemented the roboto font type with webfontloader and now I have my desired result.

That is the Config: image

image image

these are my results: Desktop: (98 - 100) image

Mobile: (90 - 95) image

Now the only differnece is that i import my Icons manually with @mdi/js.

Can you show your configuration for mdi/js import please ? I'm trying to import them because my production app version got a really bad score with lighthouse.

I also tried your configuration just above, but i got warnings about css file too big (i set extractCSS to true), did you used any purgeCSS options ? I tried a test project, with that purgeCSS config to avoid warning about vendor too big : buildModules: [ '@nuxtjs/vuetify', [ 'nuxt-purgecss', { paths: ['/node_modules/vuetify/src/**/*.ts'] } ] ], purgeCSS: { whitelist: ['v-application', 'v-application--wrap', 'v-btn'], whitelistPatterns: [ /^v-((?!application).)*$/, /^theme--*/, /.*-transition/, /.*-btn/ ], whitelistPatternsChildren: [/^v-((?!application).)*$/, /^theme--*/] }, I'm not sure that a good configuration, but it works to reduce vendor css file.

syskin avatar Jun 14 '20 07:06 syskin

@syskin For @mdi/js you need to manually import the icons you needed, and define it in vuetify.options.js

import { mdiMenu } from '@mdi/js'; // mdi-menu

export default function() {
  return {
    icons: {
      iconfont: 'mdiSvg',
      values: {
        mdiMenu,
      },
    },
  };
}

then use it in the template as follow:

<v-icon>$vuetify.icons.mdiMenu</v-icon>

As for purgeCSS, I didn't use it as it's a bit hacky in my opinion.

andrewspy avatar Jun 14 '20 16:06 andrewspy

@andrewspy Thank's for your answer. The part of your code is from a plugin ? This is a part of the nuxt/vuetify module configuration, how did you implement that in your nuxt.config.json ?

syskin avatar Jun 14 '20 18:06 syskin

@syskin In nuxt.config.js you specify this in vuetify section, i.e.

  vuetify: {
    defaultAssets: false, // for production
    optionsPath: 'vuetify.options.js',
  },

andrewspy avatar Jun 14 '20 18:06 andrewspy

@syskin For @mdi/js you need to manually import the icons you needed, and define it in vuetify.options.js

import { mdiMenu } from '@mdi/js'; // mdi-menu

export default function() {
  return {
    icons: {
      iconfont: 'mdiSvg',
      values: {
        mdiMenu,
      },
    },
  };
}

then use it in the template as follow:

<v-icon>$vuetify.icons.mdiMenu</v-icon>

As for purgeCSS, I didn't use it as it's a bit hacky in my opinion.

No you don't have to specify them in the nuxt.config.js or vuetify.options.js you can import them in yor component s. https://vuetifyjs.com/en/customization/icons/#install-material-design-icons-js-svg.

Or you use my vue-template-compiler wich does this automaticly https://github.com/mathe42/vuetify-icon-injector .

mathe42 avatar Jun 14 '20 19:06 mathe42

Thank you for your answers, that's exactly what I was looking for. I prefer the @andrewspy approach, that is more modulable and with less project dependencies, that is important to maintain my project.

syskin avatar Jun 15 '20 09:06 syskin

hello, if some one got green score, can he share with us empty template project please with the good configuration i ll tried all your solutoin but not work, always i had bad score each time i use vuetify

thanx

erradil avatar Jan 25 '21 00:01 erradil

@erradil I have green scores over 90 by using local fonts and local mdi icons instead of loading them from google.

Fonts

Use this tool to download the desired font and also to create a css file for them:

https://google-webfonts-helper.herokuapp.com/fonts/noto-sans?subsets=latin

Then download the fonts and place them in assets/fonts/ fonts

Create css file for the fonts (assets/fonts.css) and paste markup from that tool in there.

  • Remember to adjust the Customize folder prefix to ~assets/fonts/ in the css tool.
  • I used the "Best Support" option
  • I removed the SVG format as it corrupted some letters in Safari
  • Important: for each @font-face declaration add the line: font-display: swap;

The file should look something like this then:

/* noto-sans-regular - latin */
@font-face {
  font-family: 'Noto Sans';
  font-style: normal;
	font-weight: 400;
	font-display: swap;
  src: url('~assets/fonts/noto-sans-v11-latin-regular.eot'); /* IE9 Compat Modes */
  src: local(''),
       url('~assets/fonts/noto-sans-v11-latin-regular.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('~assets/fonts/noto-sans-v11-latin-regular.woff2') format('woff2'), /* Super Modern Browsers */
       url('~assets/fonts/noto-sans-v11-latin-regular.woff') format('woff'), /* Modern Browsers */
       url('~assets/fonts/noto-sans-v11-latin-regular.ttf') format('truetype'), /* Safari, Android, iOS */
}
/* noto-sans-700 - latin */
@font-face {
  font-family: 'Noto Sans';
  font-style: normal;
	font-weight: 700;
	font-display: swap;
  src: url('~assets/fonts/noto-sans-v11-latin-700.eot'); /* IE9 Compat Modes */
  src: local(''),
       url('~assets/fonts/noto-sans-v11-latin-700.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('~assets/fonts/noto-sans-v11-latin-700.woff2') format('woff2'), /* Super Modern Browsers */
       url('~assets/fonts/noto-sans-v11-latin-700.woff') format('woff'), /* Modern Browsers */
       url('~assets/fonts/noto-sans-v11-latin-700.ttf') format('truetype'), /* Safari, Android, iOS */
}

Configs and variables

// nuxt.config.js
export default {
  css: ['@/assets/fonts.css'], // use local fonts

  vuetify: {
    customVariables: ['~/assets/variables.scss'],
    optionsPath: './config/vuetify.options.js',
    treeShake: true,
    defaultAssets: false
  }
}
// assets/variables.scss
$color-pack: false;
$body-font-family: 'Noto Sans', sans-serif;
// ./config/vuetify.options.js
// nothing special here
// but variations: false will save you a few bits as less css color declarations are created
export default {
  theme: {
    options: {
      customProperties: true,
      variations: false
    },
    dark: true,
    themes: {
      dark: {
        anchor: '#e05e5e',
        primary: '#e05e5e'
      }
    }
  }
}

Icons

Installation

Install mdi icons as a dev Dependency:

npm install -D @mdi/js

Usage

In a component/page:

<template>
  <div>
    <v-icon>{{ mdiClose }}</v-icon>
  </div>
</template>

<script>
import { mdiClose } from '@mdi/js'

export default {
  data() {
    return {
      mdiClose
    }
  }
}
</script>

larzon83 avatar Jan 26 '21 13:01 larzon83

I was able to improve the Lighthouse score for Mobile to 87 and for Desktop to 94. 😃

image

image

Detailed strategy here:

https://github.com/vuetifyjs/vuetify/issues/7265#issuecomment-860389201

ManasMadrecha avatar Jun 14 '21 06:06 ManasMadrecha

Recently completed a site on Vuetify. A lot of time has been spent on improving the performance. Now everything is OK. Desktop kiev_desctop Mobile kiev_mobile

  1. all of the above recommendations
  2. in production, a really fast server
  3. you can’t make a large Vue component, or a large number of Vue components on the page, they all need to be loaded lazy and the fewer of them there are at initial load, the better, because js is single-threaded
  4. mobile lightscore perfomance is senitive to image optimisation and needs .webp

black2002 avatar Jan 18 '22 09:01 black2002