#+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