Vue SSR 组件加载问题


Posted in Javascript onMay 02, 2018

Node 端渲染提示 window/document 没有定义

Vue SSR 组件加载问题

业务场景

首先来看一个简单的 Vue 组件 test.vue

<template>
 <div>
  <h2>clientHeight: {{ clientHeight }} px </h2>
 </div>
</template>

<script type="text/babel">
 export default {
  data(){
   return {
   }
  },
  computed :{
   clientHeight() {
    return document.body.clientHeight;
   }
  },
  mounted(){
  }
 }
</script>

上面 test.vue 组件通过 Vue computed 属性 clientHeight 直接获取 document 的文档高度,这段代码在前端渲染是不会报错的,也能拿到正确的值。但如果把这个组件放到 SSR(Server Side Render) 模式下, 就会报如下错误:
ReferenceError: document is not defined

解决方案

通过 typeof 判断是否是存在 document 对象, 如果存在则执行后面代码。 这种方式虽然能解决问题, 但在 Webpack 构建压缩时, 不会执行的代码不会被剔除,也会打包到 js 文件中去, 因为这个是在运行期才知道结果的, 所以在 Webpack 构建方案中,不建议使用 typeof 方式判断。而是使用 Webpack 提供的 webpack.DefinePlugin 插件定义常量解决。

clientHeight() {
  return typeof document === 'object' ? document.body.clientHeight : '';
}

使用 Webpack 提供的 webpack.DefinePlugin 插件定义常量解决。 这里直接使用 easywebpack     https:// github.com/hubcarl/easy    webpack   内置的全局 Webpack 常量 EASY_ENV_IS_BROWSER  http:// hubcarl.github.io/easyw ebpack/webpack/env   进行 判断。 这样在构建压缩期间, 如果是 Node 模式构建, EASY_ENV_IS_BROWSER 会被替换为 false,如果是 Browser 模式构建, EASY_ENV_IS_BROWSER 会被替换为 true,最后构建后代码也就是变成了 true 或者 false 的常量。 因为这个是构建期间执行的,压缩插件剔除永远不会被执行的代码, 也就是

dead_code
clientHeight() {
  return EASY_ENV_IS_BROWSER ? document.body.clientHeight : '';
}

NPM Vue 组件 SSR 支持

针对上面这种自己写的代码,我们可以通过这种方式解决,因为可以直接修改。但如果我们引入的一个 npm Vue 插件想进行SSR渲染, 但这个插件里面使用了 window/docment 等浏览器对象, 并没有对 SSR 模式进行兼容,这个时候该如何解决呢?

一般我们通过 通过 v-if 来决定是否渲染该组件 和 Vue 只在前端挂载组件解决问题 可以解决。

通过 v-if 来决定是否渲染该组件

<template>
 <div v-if="isBrowser">
  <Loading></Loading>
 </div>
</template>
<script type="text/babel">
 export default {
  componets:{
   Loading: () =>import('vue-loading');
  }
  data(){
   return {
    isBrowser: EASY_ENV_IS_BROWSER
   }
  },
  mounted(){
  }
 }
</script>

Vue 只在前端挂载组件解决问题

<template>
 <div>
  <Loading></Loading>
 </div>
</template>

<script type="text/babel">
 export default {
  data(){
   return {
   }
  },
  beforeMount() {
   // 只会在浏览器执行 
   this.$options.components.Loading = () =>import('vue-loading');
  },
  mounted(){
  }
 }
</script>

loading 组件因为没有注册, 在 SSR 模式, <Loading></Loading> 会被原样输出到 HTML 中,不会报错且不能被浏览器识别, 在显示时不会有内容。当 SSR 直出 HTML 后,浏览器模式中执行 beforeMount 挂载组件, 从而达到解决服务端渲染报错的问题

https:// github.com/hubcarl/egg- vue-webpack-boilerplate/blob/master/app/web/page/dynamic/dynamic.vue

总结

以上所述是小编给大家介绍的Vue SSR 组件加载问题,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
Extjs显示从数据库取出时间转换JSON后的出现问题
Nov 20 Javascript
验证手机号码的JS方法分享
Sep 10 Javascript
自己实现ajax封装示例分享
Apr 01 Javascript
javascript中Date format(js日期格式化)方法小结
Dec 17 Javascript
JS中使用DOM来控制HTML元素
Jul 31 Javascript
JavaScript探测CSS动画是否已经完成的方法
Aug 30 Javascript
mongoose中利用populate处理嵌套的方法
May 26 Javascript
javascript 中模板方法单例的实现方法
Oct 17 Javascript
JS实现键值对遍历json数组功能示例
May 30 Javascript
React中嵌套组件与被嵌套组件的通信过程
Jul 11 Javascript
在vue项目中引用Iview的方法
Sep 14 Javascript
Vuex持久化插件(vuex-persistedstate)解决刷新数据消失的问题
Apr 16 Javascript
基于jquery实现左右上下移动效果
May 02 #jQuery
关于Vue在ie10下空白页的debug小结
May 02 #Javascript
解析Json字符串的三种方法日常常用
May 02 #Javascript
使用vue-cli创建项目的图文教程(新手入门篇)
May 02 #Javascript
vue中的模态对话框组件实现过程
May 01 #Javascript
vue如何通过id从列表页跳转到对应的详情页
May 01 #Javascript
使用Vue的slot插槽分发父组件内容实现高度复用、更加灵活的组件(推荐)
May 01 #Javascript
You might like
几个php应用技巧
2008/03/27 PHP
PHP响应post请求上传文件的方法
2015/12/17 PHP
什么是PHP7中的孤儿进程与僵尸进程
2019/04/14 PHP
Yii框架参数配置文件params用法实例分析
2019/09/11 PHP
JavaScript使用prototype定义对象类型
2007/02/07 Javascript
window.onbeforeunload方法在IE下无法正常工作的解决办法
2010/01/23 Javascript
PHP配置文件php.ini中打开错误报告的设置方法
2015/01/09 PHP
JavaScript中DOM详解
2015/04/13 Javascript
jQuery中serializeArray()与serialize()的区别实例分析
2015/12/09 Javascript
RequireJS多页面应用实例分析
2016/06/29 Javascript
浅谈js中几种实用的跨域方法原理详解
2016/12/02 Javascript
jQuery插件HighCharts绘制简单2D折线图效果示例【附demo源码】
2017/03/21 jQuery
详解Angular的8个主要构造块
2017/06/20 Javascript
基于 Vue 实现一个酷炫的 menu插件
2017/11/14 Javascript
深入理解JavaScript和TypeScript中的class
2018/04/22 Javascript
原生js实现获取form表单数据代码实例
2019/03/27 Javascript
编写Python CGI脚本的教程
2015/06/29 Python
python实现web方式logview的方法
2015/08/10 Python
python制作花瓣网美女图片爬虫
2015/10/28 Python
Python实现的手机号归属地相关信息查询功能示例
2017/06/08 Python
Python实现批量压缩图片
2018/01/25 Python
python3 实现爬取TOP500的音乐信息并存储到mongoDB数据库中
2019/08/24 Python
python 实现矩阵按对角线打印
2019/11/29 Python
python同义词替换的实现(jieba分词)
2020/01/21 Python
基于python3实现倒叙字符串
2020/02/18 Python
python中tkinter窗口位置\坐标\大小等实现示例
2020/07/09 Python
经典C++面试题一
2016/11/06 面试题
一些网络技术方面的面试题
2014/05/01 面试题
历史专业学生的自我评价
2014/02/28 职场文书
置业顾问岗位职责
2014/03/02 职场文书
高三上学期学习自我评价
2014/04/23 职场文书
2014年法务工作总结
2014/12/11 职场文书
工厂清洁工岗位职责
2015/02/14 职场文书
试用期自我评价范文
2015/03/10 职场文书
十二月早安励志心语大全
2019/12/03 职场文书
pytest实现多进程与多线程运行超好用的插件
2022/07/15 Python