Link Search Menu Expand Document

#+TITLE: Optimization in p.Vue

  • Gather some ideas for Philo I'd like to discuss optimization of a Vue app (I have been using Vue for 1.5 years) https://openimagesbrowser.now.sh/#/

  • Lazy loading with Dynamic Imports The component will only be rendered when called - particularly good with conditionally rendered components.

const Home = () => import('./pages/Home.vue')
```

* Lazy loading of vue-router routes
Move from importing route components statically to dynamically.

From this:
``` js
// router.js
import Home from './Home.vue'
import About from './About.vue'

const routes = [
  { path: '/', component: Home }
  { path: '/about', component: About }
]
```
To this:
``` js
// router.js
const routes = [
  { path: '/', component: () => import('./Home.vue') }
  { path: '/about', component: () => import('./About.vue') }
]
```

* Don't do vendor.js
Tempting to import all external libraries in one file - the benefit is thought to be that the files are only imported once but again we have the static/dynamic import issue.

* Prefetching
Using webpack magic comments  https://webpack.js.org/api/module-methods/[[magic-comments]]
``` js
components: {
  ModalWindow: () => import(/* webpackPrefetch: true */ './ModalWindow.vue')
}
```

TIP: If youโ€™re using Vue CLI 3 every lazily loaded resource is prefetched by default!

Important: Depending on your build configuration prefetching might work only on production mode.

* Async components
``` js
const ModalWindow = () => ({
  component: import('./ModalWindow.vue'),
  loading: LoadingComponent,
  error: ErrorComponent,
  // The error component will be displayed if a timeout is
  // provided and exceeded. Default: Infinity.
  timeout: 3000
})

export default {
  components: {
    ModalWindow
  }
}
```

TIP: You can display different error message if fetching fails due to a lack of network connectivity by using navigator.onLine property. The navigator object holds information about the browser. https://www.w3schools.com/JSREF/obj_navigator.asp

* Use bundlephobia to assess impact of 3rd Party libraries
Enter any npm package and find the package size and the performance impact.

* Analyze your bundle
You can use =webpack-bundle-analyzer=

=npm install --save-dev webpack-bundle-analyzer=

Include in your webpack configuration

``` js
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}
```

You get a graphical representation of generated code in a new tab.

* Consider which libraries are needed on which route
Don't import libraries into the main bundle if they are only used in specific routes.

* Make sure your partial imports are the most efficient
This imports the whole library
``` js
import { isNull } from 'lodash'
```
whereas this only imports the 3 lines that are relevant

``` js
import isNull from 'lodash/isNull`
```

* Component libraries
Similar problem to above.

``` js
import Vuetify from 'vuetify'

// move this to

import { VCard, VCardText, VCardTitle } from 'vuetify/lib'
```

* Tools
** Lighthouse
** vue-perf-devtool

* Use the correct Vue build
Webpack probably does this already - using the runtime-only build.

* Prerendering and SSR
Either with something like presender-spa-plugin or Nuxt.

* Disable irrelevant reactivity
If there are components that you don't need to be reactive immediately - assigning properties in the beforeCreate lifecycle hook will make them be considered static.

* Use functional templates where appropriate
If there is no declared state and only dealing with props

``` js
<template>
    // to
<template functional>
```

* Use keep-alive for dynamically loaded components
This maintains the state and prevents reloading of the data when possible.
``` js
<template>
    <component :is="currentTabeComponent" />
</template>

//to
<template>
    <keep-alive>
    <component :is="currentTabeComponent" />
    </keep-alive>
</template>

```

* v-if versus v-show
- v-if won't render the hidden component but will rerender every time it shows
- v-show will expensively load the first time but it will stay in memory after that.

* Perceived Performance
** Use GPU based transitions and animations (transform & opacity)
** Use beforeRouteEnter to retrieve your data
** Lazy load images
Using a library like vue-lazyload
** Avoid long transitions and animations