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 相关文章推荐
在线游戏大家来找茬II
Sep 30 Javascript
js获取url参数的使用扩展实例
Dec 29 Javascript
做好七件事帮你提升jQuery的性能
Feb 06 Javascript
js创建一个input数组并绑定click事件的方法
Jun 12 Javascript
javascript手工制作悬浮菜单
Feb 12 Javascript
JS实现自定义简单网页软键盘效果代码
Nov 05 Javascript
AngularJs自定义服务之实现签名和加密
Aug 02 Javascript
Jquery删除css属性的简单方法
Dec 04 Javascript
JS求Number类型数组中最大元素方法
Apr 08 Javascript
JS实现盒子跟着鼠标移动及键盘方向键控制盒子移动效果示例
Jan 29 Javascript
如何优雅地在vue中添加权限控制示例详解
Mar 07 Javascript
如何在Express4.x中愉快地使用async的方法
Nov 18 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面向对象的使用教程 简单数据库连接
2006/11/25 PHP
Destoon模板制作简明教程
2014/06/20 PHP
php解析json数据实例
2014/08/19 PHP
Yii实现MySQL多数据库和读写分离实例分析
2014/12/03 PHP
WordPress中用于获取文章作者与分类信息的方法整理
2015/12/17 PHP
php解析xml 的四种简单方法(附实例)
2016/07/11 PHP
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
2017/02/04 PHP
PHP命名空间简单用法示例
2018/12/28 PHP
借用Google的Javascript API Loader来加速你的网站
2009/01/28 Javascript
JavaScript 对象成员的可见性说明
2009/10/16 Javascript
js前台分页显示后端JAVA数据响应
2013/03/18 Javascript
简单方法判断JavaScript对象为null或者属性为空
2014/09/26 Javascript
Javascript实现的Map集合工具类完整实例
2015/07/31 Javascript
基于AngularJS前端云组件最佳实践
2016/10/20 Javascript
bootstrap 表单验证使用方法
2017/01/11 Javascript
Vue键盘事件用法总结
2017/04/18 Javascript
vue select选择框数据变化监听方法
2018/08/24 Javascript
js实现淘宝首页的banner栏效果
2019/11/26 Javascript
[02:14]DOTA2英雄基础教程 修补匠
2013/12/23 DOTA
[01:09:01]完美世界DOTA2联赛循环赛 Magma vs PXG BO2第一场 10.28
2020/10/28 DOTA
QML使用Python的函数过程解析
2019/09/26 Python
使用浏览器访问python写的服务器程序
2019/10/10 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
Tensorflow矩阵运算实例(矩阵相乘,点乘,行/列累加)
2020/02/05 Python
VSCode中autopep8无法运行问题解决方案(提示Error: Command failed,usage)
2021/03/02 Python
澳大利亚最大的在线美发和美容零售商之一:My Hair Care & Beauty
2019/08/24 全球购物
C语言开发工程师测试题
2016/12/20 面试题
SQL Server面试题
2013/04/04 面试题
工程预算与管理应届生求职信
2013/10/06 职场文书
先进工作者获奖感言
2014/02/08 职场文书
优秀语文教师事迹
2014/05/18 职场文书
保护动物的标语
2014/06/11 职场文书
Oracle更换为MySQL遇到的问题及解决
2021/05/21 Oracle
粗暴解决CUDA out of memory的问题
2021/05/22 Python
Python matplotlib 利用随机函数生成变化图形
2022/04/26 Python
分享几个实用的CSS代码块
2022/06/10 HTML / CSS