webpack的代码分包
默认的打包过程:
- 默认情况下,在构建整个组件树的过程中,因为组件和组件之间是通过
模块化直接依赖
的,那么webpack在打包时就会将组件模块打包到一起(比如一个app.js文件中); - 这个时候随着
项目的不断庞大,app.js文件的内容过大
,会造成首屏的渲染速度变慢
;
打包时,代码的分包:
- 所以,对于一些
不需要立即使用的组件
,我们可以单独对它们进行拆分
,拆分成一些小的代码块chunk.js; - 这些chunk.js会在
需要时
从服务器加载下来,并且运行代码,显示对应的内容;
那么webpack中如何可以对代码进行分包呢?
使用import函数加载模块,是异步加载;
import函数返回一个promise
import {
createApp
} from 'vue'
import App from './10_异步组件/App.vue'
//异步加载模块
import("./utils/math").then(({sum}) => {
console.log(sum(20, 30));
})
createApp(App).mount('#app')
src/utils/math.js
export function sum(a, b) {
return a + b
}
webpack在打包的时候,对于异步加载的模块,会进行分包,把其单独的打包到一个文件中
image.png
Vue中实现异步组件
如果我们的项目过大了,对于某些组件
我们希望通过异步的方式来进行加载
(目的是可以对其进行分包处理
),那么Vue中给我们提供了一个函数:defineAsyncComponent
。
defineAsyncComponent
函数调用返回一个异步组件
defineAsyncComponent接受两种类型的参数:
- 类型一:工厂函数,该工厂函数需要返回一个Promise对象;
- 类型二:接受一个对象类型,对异步函数进行配置;
工厂函数类型一的写法:
<template>
<div>
<!--3.使用异步组件-->
<async-about></async-about>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
//1.创建异步组件
const AsyncAbout = defineAsyncComponent(() => import("./AsyncAbout.vue"));
export default {
components: {
AsyncAbout, //2.注册异步组件
},
};
</script>
<style scoped></style>
接受一个对象类型类型二写法
<template>
<div>
<!--3.使用异步组件-->
<async-about></async-about>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
import Loading from "./Loading.vue";
import Error from "./Error.vue";
//1.创建异步组件
const AsyncAbout = defineAsyncComponent({
loader: () => import("./AsyncAbout.vue"), //loder的值为一个工程函数,返回一个promise
loadingComponent: Loading, //加载过程中显示的占位组件 占位组件不需要注册
errorComponent: Error, //加载失败显示的占位组件
delay: 2000, //在显示loadingComponent组件之前的延迟 | 默认值:200(单位ms)
timeout: 5000, //加载组件的时间超过了设定值,将显示错误组件 | 默认值 Inifinity(即永不超时), 单位ms
onError(err, retry, fail, attemps) {//监听错误事件
console.log(err) //错误信息
//retry 调用此函数代表尝试重新加载组件
cnsole.log(attemps) //尝试重新加载的次数,超过次数不再加载
//fail 调用此函数,代表加载失败,不再尝试加载了
if(attempts <= 3) {
retry()
}else {
fail()
}
}
});
export default {
components: {
AsyncAbout, //2.注册异步组件
},
};
</script>
<style scoped></style>
异步组件和Suspense
注意:目前(2021-06-08)Suspense显示的是一个实验性的特性,API随时可能会修改。
Suspense是一个内置的全局组件,该组件有两个插槽:
- default:如果default可以显示,那么显示default的内容;
- fallback:如果default无法显示,那么会显示fallback插槽的内容;
<template>
<div>
<suspense>
<template #default>
<!--3.使用异步组件-->
<async-about></async-about>
</template>
<template #fallback>
<loading></loading>
</template>
</suspense>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
//1.创建异步组件
const AsyncAbout = defineAsyncComponent(() => import("./AsyncAbout.vue"));
import Loading from "./Loading.vue";
export default {
components: {
AsyncAbout, //2.注册异步组件
Loading
},
};
</script>
<style scoped></style>
异步组件的使用场景
如果动态渲染的组件为同步加载的组件,webpack打包的时候,会把这些同步加载的组件,都打包到app.js中,app.js文件过大,会影响首屏加载速度
使动态渲染的组件为异步组件,webpack打包的时候,会把各个异步组件单独打包一个文件,那些组件不会被打包到app.js中
<template>
<div>
<button v-for="item in list" :key="item"
:class="{active: curItem === item}"
@click="btnClick(item)">{{item}}</button>
<keep-alive include="async-about">
<component name="why" :age="18" :is="curItem"
@pageClick="pageClick"></component>
</keep-alive>
</div>
</template>
<script>
import { defineAsyncComponent } from "vue";
const AsyncAbout = defineAsyncComponent(() => import('./pages/About.vue'))
const AsyncHome = defineAsyncComponent(() => import('./pages/Home.vue'))
const AsyncCategory = defineAsyncComponent(() => import('./pages/Category.vue'))
export default {
components: {
AsyncAbout,
AsyncHome,
AsyncCategory
},
data() {
return {
list: ['async-home', 'async-about', 'async-category'],
curItem: 'home'
}
},
methods: {
btnClick(item) {
this.curItem = item
},
pageClick() {
console.log('页面被点击')
}
}
}
</script>
<style scoped>
.active {
color: red
}
</style>
此文档主要内容来源于王红元老师的vue3+ts视频教程
网友评论