vue.js 开发系列(三)Skeleton 骨架屏渲染
栏目: JavaScript · 发布时间: 5年前
内容简介:简单来说,骨架屏(skeleton screen) 就是一个页面从就我的理解,骨架屏优化是有一定场景的,包括且不限于以下几种情况:上图形象地解释了两个多页面程序之间的切换,用Skeleton Screen 去优化用户观感的方案。
简单来说,骨架屏(skeleton screen) 就是一个页面从 html 下载完成 到 js 下载完成并且执行 数据渲染 这两个时间点之间暂时渲染页面基本结构的方案。
就我的理解,骨架屏优化是有一定场景的,包括且不限于以下几种情况:
- 有懒加载机制的SPA路由
- 多页面程序的首页渲染
- SPA 中的非懒加载路由,但是数据量很大,完全load 并渲染数据需要花较长时间
上图形象地解释了两个多页面程序之间的切换,用Skeleton Screen 去优化用户观感的方案。
Skeleton 渲染是在 前端项目编译时 完成的,与之相对应的是组件在浏览器runtime实时渲染成DOM,从技术上讲就是在服务器端 预先把组件布局和数据渲染成html 字符串 并且注入html 文件中。这需要服务器端渲染(ssr) 的支持。如react 和 vue.js 这样依赖虚拟DOM 的前端框架天然是支持服务器端渲染的。因为只需要一个 JavaScript 在服务器端的执行环境(例如V8 引擎)就可以轻易创建虚拟Dom并且映射为DOM tree。基于虚拟dom的服务器端渲染,最早起源于react,可以参考 strikingly 的技术博客
服务器端渲染
服务器端渲染作为skeleton screen的基本技术栈,可以参考各前端框架的官方文档,例如vue-ssr guide. 主要是依赖vue-server-renderer 这个库来实现
拿vue.js 组件来说,在node.js 中渲染为 HTML 字符串可以简单分为几步:
// 第 1 步:创建一个 Vue 实例 const Vue = require('vue') const app = new Vue({ // el: 是不需要的,因为一旦设置目标 el,就会涉及document 操作 template: `<div>Hello World</div>` }) // 第 2 步:创建一个 renderer const renderer = require('vue-server-renderer').createRenderer() // 第 3 步:将 Vue 实例渲染为 HTML renderer.renderToString(app, (err, html) => { if (err) throw err console.log(html) // => <div data-server-rendered="true">Hello World</div> }) 复制代码
上面的官方DEMO 很简单,直接在nodejs 脚本文件中定义vue 组件。但实际应用中我们的组件一般都比较复杂,可能是一个入口 app.vue,依赖了好几个组件,所以要用另外的方式去引入 new Vue 产生的 vm 对象. 这个vm 对象作为 renderer.renderToString 函数的第一个参数是最核心的。实际上通过跟踪 vue-server-renderer 的源码,ssr 还是依靠vue组件的render 函数来完成大部分工作 ,render 函数是 vue 组件的核心函数。
| installSSRHelpers(component); renderToString -> createRenderFunction -> | normalizeRender(component); // get component render function | renderNode(component._render(), true, context); // call component render to VNode. 复制代码
几个坑
- document not defined
服务器端渲染并 不等同于在服务器端启动一个浏览器进程 ,所以无法获取浏览器窗体中的window,document 等全局对象。一旦服务器端渲染的js 脚本中涉及到document 操作,就会报这个 document not defined 的错误。
所以要么就在vue 组件中或者所有依赖包中用到document 的地方都要做检测,要么就在服务器端渲染之前给global 对象加上document 定义 github issue
- unexpected token =
在vue-server-renderer 的执行过程中,提供了把vue 组件渲染成html 片段并且插入某个 template HTML 中的API, 在创建Renderer 的时候传入一个template。后来发现ssr 的 template 中是 不能包含类似这种 <%= ddd > 符号 的,也就是template 必须得 符合vue 的template 语法 。
// 最后ssr 就会输出 Vue 组件的内容,并且注入到template 中 注释 <!--vue-ssr-outlet--> 的地方 const renderer = createRenderer({ template: require('fs').readFileSync('./index.template.html', 'utf-8') }) const context = { title: 'Hello' } renderer.renderToString(app, context, (err, html) => { // 页面模板中 {{ title }} 将会是 "Hello" }) 复制代码
具体参考ssr 使用页面模板。 因为有的后端 程序员 习惯了 asp 或者 jsp 的template 语法,以 <%= 等作为数据插值表达式的开头,会引起 vue ssr 的编译失败。
写在后面
综上,这次我只是简单分析记录了下 Skeleton 骨架屏实现的第一部分,就是server side render,这是预先渲染的技术前提。实际上,这种后端拼接Html 字符串的活在 php 年代,python server中,甚至node.js server 中我们早就干过了(ejs 或者 jade)。 本质上都是拼接Html 字符串,提高SEO 和首屏响应 。
在Github 上有许多基于服务器端渲染的静态网站生成器或者 博客工具,可以实现比较流畅的浏览体验, 例如: vuepress .
关于骨架屏的实现,业内已经有很成熟的方案,既有基于 ssr 的,也有直接基于浏览器内核起个进程预渲染的,完全不用vue 的ssr 技术栈。下一次再具体分享下后者
参考阅读:
essential-guide-to-improve-seo-in-single-page-application-vuejs
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
游戏人工智能编程案例精粹
巴克兰德 (Mat Buckland) / 罗岱 / 人民邮电出版社 / 2008年06月 / 55.00元
《游戏人工智能编程案例精粹》适合对游戏AI开发感兴趣的爱好者和游戏AI开发人员阅读和参考。一起来看看 《游戏人工智能编程案例精粹》 这本书的介绍吧!