Light & Lazy Asynchronous patterns for Vue Apps

Toronto 16th Nov 2018

GitHub icon
Twitter icon

Eduardo

San Martin Morote

Vue core team

Remote Freelance Developer

ย 

GitHub icon

Prototyping is fun

ReBuild plugins in Vue

Code Splitting

You should split your code

It all starts with webpack

Dynamic Import

import('a_package').then(module => module.default)
import('./utils.js').then(module => module.log)
const aPackage = () => import('a_package')
const utils = () => import('./utils.js')

Configure Webpack

SplitChunksPlugin

๐Ÿ“šDocs

Prefetch

import(/* webpackPrefetch: true */ 'LoginModal')
<link rel="prefetch" href="login-modal-chunk.js" />

Preload

import(/* webpackPreload: true */ 'ChartingLibrary')
<link rel="preload" href="chunk.js" />

Lazy-Loading components

โœจAnywhere

import Calendar from '@/components/Calendar.vue'
const Calendar = () => import('@/components/Calendar.vue')

Per-Page

// router.js
const Home = () => import('@/views/Home')
const User = () => import('@/views/User')

const routes = [
  { path: '/', component: Home },
  { path: '/users/:id', component: User },
]

in-componenT

// App.vue
const Search = () => import('@/components/Search')

export default {
  components: { Search }
}

Chunks

Search.vue

The real deal

โœ‚๏ธ vendors

Lazy load Recipee ๐Ÿฅ˜

  • Local imports
  • Lazy load view components

PROFIT ๐Ÿ”ฅ

Dynamic Components

in-template

<component :is="dynamicComponent"/>
// inside of a component method

// local or global component
this.dynamicComponent = 'UserCard'

// component descriptor
// import UserCard from './UserCard'
this.dynamicComponent = UserCard

In-Render functions

export default {
  render (h) {
    return h(this.dynamicComponent)
  },
  methods: {
    changeDisplayedComponent () {
      this.dynamicComponent = 'UserCard'
      // or
      this.dynamicComponent = UserCard
    }
  }
}

โœจAnywhere

import Calendar from '@/components/Calendar.vue'
const Calendar = () => import('@/components/Calendar.vue')

Dynamic Lazy components

<component :is="dynamicComponent"/>
// inside of a component method
this.dynamicComponent = () => import('./UserCard')
render(h) { return h(this.dynamicComponnet) }

Dynamic Imports with Expressions

import(`@/components/async/${name}.vue`)

let webpack creates chunks ๐Ÿ‘Œ

Careful...

import(myComponentPath) // ๐Ÿ˜ฑ โ˜ ๏ธ

your app

Hint Webpack the best you can

import(myComponentPath) // ๐Ÿ˜ฑ โ˜ ๏ธ
import(`@/components/Lazy${name}.vue`) // ๐Ÿ™Œ
import(`@/components/async/${name}.vue`) // ๐Ÿ’ฏ

Lazy loading Dynamic Components

USage

<ExamplePreview name="counter"/>

dynamic components + computed = ๐Ÿ‘Œ

computed: {
  demoComponent() {
    // make demoComponent depend on name
    const name = this.name
    return () =>
      import(`@docs/examples/${name}/index.js`)
  }
}
<component :is="demoComponent"/>

Analyzing your app

Monster

when your app is unmaintainable but you still care

vue ui

Lazy Load

  • Local imports
  • Always lazy load views
  • Lazy load big local components

Dynamic import expressions

  • As precise as possible
  • Prefetch flag (can wait)
  • Preload (needed now)

Handling Errors

โŒ Error

// in a component method
this.error = null
return import('./Component.vue').catch(err => {
  this.error = err
})
<p class="danger" v-if="error">{{ error }}</p>

โณ LOading

this.error = null
this.pending = true
return import('./Component.vue').then(module => {
  this.pending = false
  return module
}).catch(err => this.error = err)
<p class="danger" v-if="error">{{ error }}</p>
<p class="info" v-else-if="pending">Loading...</p>

when you realize you have been writing the same thing over and over

Async component factory

const AsyncComponent = () => ({
  component: import('./MyComponent.vue'),
  loading: LoadingComponent,
  error: ErrorComponent,
  delay: 200,
  timeout: 3000
})

๐Ÿ’ Vue-promised

<Promised :promise="componentPromise">
  <p slot="pending">Loading component</p>
  <component
    slot-scope="module"
    :is="module.default"
  />
  <p slot="rejected" slot-scope="error">
    {{ error.message}}
  </p>
</Promised>

๐Ÿ‘‰ Github repo

Thanks! ๐Ÿ––

GitHub icon
Made with Slides.com