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 相关文章推荐
用于deeplink的js方法(判断手机是否安装app)
Apr 02 Javascript
node.js中的fs.createWriteStream方法使用说明
Dec 17 Javascript
实例代码详解javascript实现窗口抖动及qq窗口抖动
Jan 04 Javascript
js如何准确获取当前页面url网址信息
Sep 13 Javascript
jQuery替换节点用法示例(使用replaceWith方法)
Sep 08 Javascript
JS基于递归实现倒计时效果的方法
Nov 26 Javascript
ionic实现下拉刷新载入数据功能
May 11 Javascript
性能优化篇之Webpack构建速度优化的建议
Apr 03 Javascript
解决cordova+vue 项目打包成APK应用遇到的问题
May 10 Javascript
js获取 gif 的帧数的代码实例
Sep 10 Javascript
JS深入学习之数组对象排序操作示例
May 01 Javascript
详解JavaScript作用域 闭包
Jul 29 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和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍
2011/07/03 PHP
从零开始学YII2框架(二)通过 Composer 安装扩展插件
2014/08/20 PHP
简单谈谈PHP vs Node.js
2015/07/17 PHP
全面解读PHP的人气开发框架Laravel
2015/10/15 PHP
PHP正则表达式之捕获组与非捕获组
2015/11/06 PHP
浅析Yii2缓存的使用
2016/05/10 PHP
利用js跨页面保存变量做菜单的方法
2008/01/17 Javascript
JavaScript 设计模式学习 Singleton
2009/07/27 Javascript
基于Jquery的跨域传输数据(JSONP)
2011/03/10 Javascript
js+xml生成级联下拉框代码
2012/07/24 Javascript
jquery foreach使用示例
2013/09/12 Javascript
javascript结合ajax读取txt文件内容
2014/12/05 Javascript
详解Node.js包的工程目录与NPM包管理器的使用
2016/02/16 Javascript
js仿百度切换皮肤功能(html+css)
2016/07/10 Javascript
JS中如何实现点击a标签返回页面顶部的问题
2017/01/19 Javascript
angularJs提交文本框数据到后台的方法
2018/10/08 Javascript
微信小程序修改数组长度的问题的解决
2019/12/17 Javascript
JS常用排序方法实例代码解析
2020/03/03 Javascript
[01:52]深扒TI7聊天轮盘语音出处7
2017/05/11 DOTA
[02:27]2018DOTA2亚洲邀请赛赛前采访-OpTic
2018/04/03 DOTA
详尽讲述用Python的Django框架测试驱动开发的教程
2015/04/22 Python
使用Python中的tkinter模块作图的方法
2017/02/07 Python
Python连接数据库学习之DB-API详解
2017/02/07 Python
Python 爬虫图片简单实现
2017/06/01 Python
Python读取excel指定列生成指定sql脚本的方法
2018/11/28 Python
python 自定义对象的打印方法
2019/01/12 Python
Windows下PyCharm配置Anaconda环境(超详细教程)
2020/07/31 Python
python如何使用腾讯云发送短信
2020/09/17 Python
轻金属冶金专业毕业生自荐信
2013/11/02 职场文书
迎新晚会邀请函
2014/02/01 职场文书
感恩母亲节演讲稿
2014/05/07 职场文书
党员批评与自我批评总结
2014/10/15 职场文书
2014年小学数学教师工作总结
2014/12/03 职场文书
经理岗位职责
2015/02/02 职场文书
python控制台打印log输出重复的解决方法
2021/05/14 Python
详解Mysql和Oracle之间的误区
2021/05/18 MySQL