SSR存在的问题

215 阅读1分钟

服务器上的window的问题

通过JSDOM来模拟浏览器环境

import * as jsdom from 'jsdom'
const { JSDOM } = jsdom
const resourceLoader = new jsdom.ResourceLoader({
  userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
})
const dom = new JSDOM('', {
  url: 'http://192.168.10.120:3001/index.template.html',
  resources: resourceLoader
})
global.window = dom.window
global.document = window.document
global.navigator = window.navigator
global.sessionStorage = window.sessionStorage
global.location = window.location
global.localStorage = window.localStorage
// @ts-ignore
global.CD = window.CD
// @ts-ignore
window.isNode = true

特殊组件进行客户端渲染

有些组件需要依赖浏览器环境,需要使用vue-no-ssr插件进行渲染,如富文本,地图等

npm i vue-no-ssr --save
impoer NoSSR form 'vue-no-ssr';
export default {
 components: {
   'no-ssr': NoSSR
  }
}
<no-ssr>
  <editor-component></editor-component>
</no-ssr>

服务端渲染HTML标签与客户端不一致

在开发模式下,vue将推断客户端生成的虚拟DOM树,是否与服务器渲染的DOM结构匹配。如果无法匹配,它将退出混合模式,丢弃现有的DOM并从头开始渲染,在生产模式下,此检测会被跳过,以避免性能损耗。

    The client-side rendered virtual DOM tree is not matching server-rendered content. This is likely caused by incorrect HTML markup, for example nesting block-level elements inside <p>, or missing <tbody>. Bailing hydration and performing full client-side render.

使用【ssr + 客户端混合】时,需要了解的一件事,浏览器可能会更改的一些特殊的html结构。如

<table>
  <tr><td>hi</td></tr>
</table>

浏览器会在table 内部自动注入tbody,然而,由于 Vue 生成的虚拟 DOM (virtual DOM) 不包含 tbody,所以会导致无法匹配。为能够正确匹配,请确保在模板中写入有效的 HTML。

<table>
  <tbody>
    <tr><td>hi</td></tr>
  </tbody>
</table>

node中没有FormData这个类

使用qs.stringify

import qs from 'qs'
const promise = function(fn){
  return new Promise((resolve, reject) => {
    fn
      .then(res => {
        resolve(res);
      })
      .catch(err => {
        const errMsg = err.response && err.response.data.msg || ''
        reject(errMsg.replace(/[errs]/, '').replace(/[erre]/, ''))
      });
  });
}
export default {
  getData(data) {
     return promise(
        axios.post('/system/getData', qs.stringify(data))
      );
   },
}