Skip to content

Chore/async components #3

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# vue-template - Making async/lazy load of components

Hi, everyone! 👋

This is a nice repo with some approaches to use in VueJS (2.x) projects. [You may find more here](https://github.com/open-ish/vue2-template) or change by the branch at GitHub.

If you wanna, let's get in touch!

## What're we gonna use?

- [VueJS (2.x | 3.x)](https://vuejs.org/)

## Summary

- [What does it resolve?](#What does it resolve?)
- [Key files](#Key-files)

## What does it solve?

Once the application gets huge, keep it with good performance is one of the most challenging. A good approach that helps us is to create small chunks and get them smartly. Getting components async/lazy and choose the right moment to do it can help us a lot. vue-cli (using behind the scenes Vue and webpack) give us a nice approach to delay some chunks and reuse them when they are called in more than one place.

The best part about it is easiness. You only will need to `change the way you are importing components` and combine it with a `v-if directive`. Let's take a look.

### Import differences

First of all, let's see the difference between the normal import and async/lazy import.

**Normal import**

```sh
<template>
<div>
<!-- Once rendering the dad component, myNomalComponent also will be rendered -->
<myNomalComponent/>
</div>
</template>

import Vue from "vue";
import myNomalComponent from './myNomalComponent.vue'

export default Vue.extend({
components: {
myNomalComponent
}
})
```

**Async/Lazy import**

```sh
<template>
<div>
<!-- This combination between the v-if directive and the import in a function-->
<!-- makes the component been rendered into a separated chunk.-->
<myAsyncComponent v-if="isOpened"/>

<button @click="isOpened=true"> btn </button>
</div>
</template>

import Vue from "vue";

export default Vue.extend({
components: {
myAsyncComponent: () => import('./myAsyncComponent.vue')

// on vue 3
// you must import defineAsyncComponent from vue ;)
myAsyncComponentWithVue3: defineAsyncComponent(() => import('myAsyncComponentWithVue3.vue'))
},
data() {
return {
isOpened: false
}
}
})
```

## Key files
13 changes: 13 additions & 0 deletions src/components/Alert.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<v-alert dense type="info">
<slot />
</v-alert>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
name: "Alert",
});
</script>
45 changes: 45 additions & 0 deletions src/components/AsyncLazyImport.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<template>
<div>
<v-card class="mx-auto" max-width="344" outlined>
<v-card-text>
<Alert v-if="isFirstAsyncAlertOpened" dense type="info">
Rendering my first component </Alert
><v-card-actions>
<v-btn outlined rounded text @click="openFirstAsyncAlert()">
First Button
</v-btn>
</v-card-actions>
</v-card-text>
</v-card>
</div>
</template>

<script lang="ts">
import Vue from "vue";
import Loading from "./loading.vue";
import Erro from "./error.vue";

const Alert = () => ({
component: import(/* webpackChunkName: "async-lazy-import" */ "./Alert.vue"),
loading: Loading,
error: Erro,
timeout: 5000,
});

export default Vue.extend({
name: "AsyncLazyImport",
components: {
Alert,
},
data() {
return {
isFirstAsyncAlertOpened: false,
};
},
methods: {
openFirstAsyncAlert() {
this.isFirstAsyncAlertOpened = !this.isFirstAsyncAlertOpened;
},
},
});
</script>
13 changes: 13 additions & 0 deletions src/components/error.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div>
<h3>Error</h3>
</div>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
name: "Error",
});
</script>
13 changes: 13 additions & 0 deletions src/components/loading.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<div>
<h3>loading</h3>
</div>
</template>

<script lang="ts">
import Vue from "vue";

export default Vue.extend({
name: "Loading",
});
</script>
11 changes: 5 additions & 6 deletions src/router/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,12 @@ const routes: Array<RouteConfig> = [
component: Home,
},
{
path: "/about",
name: "About",
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
path: "/async-import",
name: "AsyncImport",
component: () =>
import(/* webpackChunkName: "about" */ "../views/About.vue"),
import(
/* webpackChunkName: "async-import" */ "../views/AsyncLazyImportView.vue"
),
},
];

Expand Down
5 changes: 0 additions & 5 deletions src/views/About.vue

This file was deleted.

18 changes: 18 additions & 0 deletions src/views/AsyncLazyImportView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<template>
<div class="about">
<h1>Async/Lazy import</h1>
<AsyncLazyImport />
</div>
</template>
<script lang="ts">
import Vue from "vue";
import AsyncLazyImport from "../components/AsyncLazyImport.vue";

export default Vue.extend({
name: "AsyncLazyImportView",

components: {
AsyncLazyImport,
},
});
</script>