Vue服务端渲染实践之Web应用首屏耗时最优化方案

2020-06-14 06:25:04易采站长站整理
Vuex
状态中。

另一个需要关注的问题是在客户端,在挂载到客户端应用程序之前,需要获取到与服务器端应用程序完全相同的数据 – 否则,客户端应用程序会因为使用与服务器端应用程序不同的状态,然后导致混合失败。

目前较好的解决方案是,给路由匹配的一级子组件一个

asyncData
,在
asyncData
方法中,
dispatch
对应的
action
asyncData
是我们约定的函数名,表示渲染组件需要预先执行它获取初始数据,它返回一个
Promise
,以便我们在后端渲染的时候可以知道什么时候该操作完成。注意,由于此函数会在组件实例化之前调用,所以它无法访问
this
。需要将
store
和路由信息作为参数传递进去:

举个例子:


<!-- Lung.vue -->
<template>
<div></div>
</template>

<script>
export default {
// ...
async asyncData({ store, route }) {
return Promise.all([
store.dispatch('getA'),
store.dispatch('myModule/getB', { root:true }),
store.dispatch('myModule/getC', { root:true }),
store.dispatch('myModule/getD', { root:true }),
]);
},
// ...
}
</script>

entry-server.js
中,我们可以通过路由获得与
router.getMatchedComponents()
相匹配的组件,如果组件暴露出
asyncData
,我们就调用这个方法。然后我们需要将解析完成的状态,附加到渲染上下文中。


const createApp = require('./app');

module.exports = context => {
return new Promise((resolve, reject) => {
const { app, router, store } = createApp(context);
// 针对没有Vue router 的Vue实例,在项目中为列表页,直接resolve app
if (!router) {
resolve(app);
}
// 设置服务器端 router 的位置
router.push(context.url.replace('/base', ''));
// 等到 router 将可能的异步组件和钩子函数解析完
router.onReady(() => {
const matchedComponents = router.getMatchedComponents();
// 匹配不到的路由,执行 reject 函数,并返回 404
if (!matchedComponents.length) {
return reject('匹配不到的路由,执行 reject 函数,并返回 404');
}
Promise.all(matchedComponents.map(Component => {