性能优化之SSR服务端渲染动态SDK组件的注意点
看之前需要有SSR服务端渲染的相关知识积累
背景
在做性能优化时,碰到一个场景:
- HTML页面中的某一大块内容是通过引SDK加载出来的。但问题就是,这块内容无法支持SSR服务端渲染,只能在客户端渲染。这样会造成一个很大的时延
这个场景大家平常可能会比较少碰到。我也是因为我们业务比较多,比较复杂,才碰到这么一个特殊的场景
场景条件
- vue
- SSR服务
- 某块内容由SDK加载,这块内容无法支持SSR服务端渲染,只能在客户端渲染
ps:SDK可以理解为 封装好的一个组件,里面有完全的功能,比如一个很复杂的表单。 后面就以表单举例,SDK就可以理解成一个表单。要渲染这个表单,我们需要 import ... from 'sdk.js'
分析:为什么无法支持SSR服务端渲染?
首先分析如何使用这个SDK,发现有以下几个特点
- 必须要有一个dom,并且要写id,和SDK约定好的id
<div id="__oneForm__"></div> - 放mounted和created等 服务端都无法渲染出来,客户端正常渲染
<template>
<div>
<div id="__oneForm__"></div>
</div>
</template>
<script>
import oneForm from 'sdk.js'
export default {
mounted () {
new oneForm({
...配置项
})
}
}
</script>
分析:
- 服务端无法渲染出来,很可能和dom有关系,服务端没有dom
- 看这种写法和 new Vue() 比较像,稍微了解vue的源码的话(可以看我以前的文章,有基础的vue源码解析),就知道源码会有一个 $mount('#app')的过程,实际上就是去页面上,把
div id="app">domNode.replaceChild() 掉,所以依赖真实的dom,服务端没有dom所以行不通 - 看了一下SDK的源代码,确实用的new Vue()
分析到这,看起来是已经无解,尬住了
但实际上,再仔细想想的话,其实有解决办法
解决办法
想想同类型的场景,比如ui组件库,为什么能支持SSR的服务端渲染?
- 是因为他们都做成了子组件( Vue.component() / Vue.use() ),所以组件级别的SSR服务端渲染还是能支持的
所以,解决思路是
- 把SDK稍微改造一下,改成
Vue.component() 或 Vue.use()的方式去注册组件,而不是new Vue({ el: '#app', ... })
码子不易,点赞鼓励!