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 相关文章推荐
img的onload的另类用法
Jan 10 Javascript
javascript 类型判断代码分析
Mar 28 Javascript
Jquery 数据选择插件Pickerbox使用介绍
Aug 24 Javascript
Jquery实现图片左右自动滚动示例
Sep 25 Javascript
js对文章内容进行分页示例代码
Mar 05 Javascript
JavaScript调试工具汇总
Dec 23 Javascript
jQuery实现无限往下滚动效果代码
Apr 16 Javascript
jQuery中的通配符选择器使用总结
May 30 Javascript
js实现PC端和移动端刮卡效果
Mar 27 Javascript
React Native实现进度条弹框的示例代码
Jul 17 Javascript
详解vue-cli 构建Vue项目遇到的坑
Aug 30 Javascript
Vue源码中要const _toStr = Object.prototype.toString的原因分析
Dec 09 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
用Socket发送电子邮件(利用需要验证的SMTP服务器)
2006/10/09 PHP
微信支付开发订单查询实例
2016/07/12 PHP
jquery 实现的全选和反选
2009/04/15 Javascript
jQuery源码中的chunker 正则过滤符分析
2012/07/31 Javascript
JS图片根据鼠标滚动延时加载的实例代码
2013/07/13 Javascript
jquery下div 的resize事件示例代码
2014/03/09 Javascript
深入分析Javascript跨域问题
2015/04/17 Javascript
Javascript实现Array和String互转换的方法
2015/12/21 Javascript
js 获取范围内的随机数实例代码
2016/08/02 Javascript
基于AGS JS开发自定义贴图图层
2017/03/31 Javascript
关于vue.js过渡css类名的理解(推荐)
2017/04/10 Javascript
VueRouter导航守卫用法详解
2017/12/25 Javascript
在 Typescript 中使用可被复用的 Vue Mixin功能
2018/04/17 Javascript
详解javascript中的变量提升和函数提升
2018/05/24 Javascript
Node.js对MongoDB进行增删改查操作的实例代码
2019/04/18 Javascript
非常漂亮的js烟花效果
2020/03/10 Javascript
解决vue单页面应用进入页面加载所有 js 的问题
2020/08/12 Javascript
PHP 502bad gateway原因及解决方案
2020/11/13 Javascript
Python简单实现TCP包发送十六进制数据的方法
2016/04/16 Python
用Python一键搭建Http服务器的方法
2018/06/01 Python
Python闭包执行时值的传递方式实例分析
2018/06/04 Python
python跳过第一行快速读取文件内容的实例
2018/07/12 Python
python绘制简单彩虹图
2018/11/19 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
2019/12/04 Python
tensorflow入门:tfrecord 和tf.data.TFRecordDataset的使用
2020/01/20 Python
Python 面向对象部分知识点小结
2020/03/09 Python
python 如何实现遗传算法
2020/09/22 Python
美国内衣品牌:Leonisa
2016/08/14 全球购物
Allen Edmonds官方网站:一家美国优质男士鞋类及配饰制造商
2019/03/12 全球购物
BIFFI美国站:意大利BIFFI BOUTIQUES豪华多品牌时装零售公司
2020/02/11 全球购物
小学生安全保证书
2014/02/01 职场文书
投标担保书范文
2014/04/02 职场文书
幼儿园圣诞节活动总结
2015/05/06 职场文书
关于做家务的心得体会
2016/01/23 职场文书
新手入门Jvm-- JVM对象创建与内存分配机制
2021/06/18 Java/Android
JavaScript实现一键复制内容剪贴板
2022/07/23 Javascript