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

2020-06-14 06:25:04易采站长站整理

}

注:在我所在的项目中,需要动态判断是否需要注册

DicomView
,只有在客户端才初始化
DicomView
,由于
Node.js
环境没有
window
对象,对于代码运行环境的判断,可以通过
typeof window === 'undefined'
来进行判断。

避免创建单例

Vue SSR
文档所述:

当编写纯客户端 (client-only) 代码时,我们习惯于每次在新的上下文中对代码进行取值。但是,Node.js 服务器是一个长期运行的进程。当我们的代码进入该进程时,它将进行一次取值并留存在内存中。这意味着如果创建一个单例对象,它将在每个传入的请求之间共享。如基本示例所示,我们为每个请求创建一个新的根 Vue 实例。这与每个用户在自己的浏览器中使用新应用程序的实例类似。如果我们在多个请求之间使用一个共享的实例,很容易导致交叉请求状态污染 (cross-request state pollution)。因此,我们不应该直接创建一个应用程序实例,而是应该暴露一个可以重复执行的工厂函数,为每个请求创建新的应用程序实例。同样的规则也适用于 router、store 和 event bus 实例。你不应该直接从模块导出并将其导入到应用程序中,而是需要在 createApp 中创建一个新的实例,并从根 Vue 实例注入。

如上代码所述,

createApp
方法通过返回一个返回值创建
Vue
实例的对象的函数调用,在函数
createVueInstance
中,为每一个请求创建了
Vue
Vue Router
Vuex
实例。并暴露给
entry-client
entry-server
模块。

在客户端

entry-client.js
只需创建应用程序,并且将其挂载到
DOM
中:


import { createApp } from './app';

// 客户端特定引导逻辑……

const { app } = createApp();

// 这里假定 App.vue 模板中根元素具有 `id="app"`
app.$mount('#app');

服务端

entry-server.js
使用
default export
导出函数,并在每次渲染中重复调用此函数。此时,除了创建和返回应用程序实例之外,它不会做太多事情 – 但是稍后我们将在此执行服务器端路由匹配和数据预取逻辑: