在开发webapp的时候总是会受到首屏加载时间过长的影响,主流的解决方法是在载入完成之前显示loading图效果,而一些大公司会配置一套服务端渲染的架构来解决这个问题。考虑到ssr所要解决的一系列问题,越来越多的APP采用了“骨架屏”的方式去提升用户体验。

一、分析Vue页面的内容加载过程

vue项目中的入口index.html只有简单的内容:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><title>Document</title>
</head>
<body><div id="root">        </div><script type="text/javascript" src="bundle.js"></script></body>
</body>
</html>

当js执行完之后,会用vue渲染成的dom将div#root完全替换掉。
我们在div#root中加入模拟骨架屏,在Chrome开发者工具调整网速:

<div id="root">这里是骨架屏
</div>

由此可知,将骨架屏内容直接插入div#root中即可实现骨架屏。

二、使用vue-server-renderer来实现骨架屏

我们需要骨架屏也是一个单独的.vue文件,因此我们需要用到vue-server-renderer。对vue服务端渲染有所了解的同学一定知道,这个插件能够将vue项目在node端打包成一个bundle,然后由bundle生成对应的html。
首先是生成项目:

.
├── build
│   ├── webpack.config.client.js
│   └── webpack.config.server.js
├── src
│   └── views
│        ├── index
│        │   └── index.vue
│        ├── skeleton
│        │   └── skeleton.vue
│        ├── app.vue
│        ├── index.js
│        └── skeleton-entry.js
├── index.html
└── skeleton.js
└── package.json

vue的服务端渲染一般会用vue-server-renderer将整个项目在node端打包成一份bundle,而这里我们只要一份有骨架屏的html,所以会有一个单独的骨架屏入口文件skeleton-entry.js,一个骨架屏打包webpack配置webpack.config.server.js,而skeleton.js作用是将webpack打包出来的bundle写入到index.html中。

//skeleton-entry.js
import Vue from 'vue'
import Skeleton from './views/skeleton/skeleton.vue'export default new Vue({components: {Skeleton},template: '<skeleton />'
})

//webpack.config.server.js
const path = require('path')
const { VueLoaderPlugin } = require('vue-loader')
const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')module.exports = {mode: process.env.NODE_ENV,target: 'node',entry: path.join(__dirname, '../src/skeleton-entry.js'),output: {path: path.join(__dirname, '../server-dist'),filename: 'server.bundle.js',libraryTarget: 'commonjs2'},module: {rules: [{test: /\.vue$/,loader: 'vue-loader'},{test: /\.css$/,use: ['vue-style-loader','css-loader']}    ]},externals: Object.keys(require('../package.json').dependencies),resolve: {alias: {'vue$': 'vue/dist/vue.esm.js'}},plugins: [new VueLoaderPlugin(),new VueSSRServerPlugin({filename: 'skeleton.json'})]
}

其中骨架屏的webpack配置因为是node端,所以需要target: 'node' libraryTarget: 'commonjs2'。在VueSSRServerPlugin中,指定了其输出的json文件名。当执行webpack会在/server-dist目录下生成一个skeleton.json文件,这个文件记载了骨架屏的内容和样式,会提供给vue-server-renderer使用。

//skeleton.js
const fs = require('fs')
const path = require('path')const createBundleRenderer = require('vue-server-renderer').createBundleRenderer// 读取`skeleton.json`,以`index.html`为模板写入内容
const renderer = createBundleRenderer(path.join(__dirname, './server-dist/skeleton.json'), {template: fs.readFileSync(path.join(__dirname, './index.html'), 'utf-8')
})// 把上一步模板完成的内容写入(替换)`index.html`
renderer.renderToString({}, (err, html) => {fs.writeFileSync('index.html', html, 'utf-8')
})

  注意,作为模板的html文件,需要在被写入内容的位置添加<!--vue-ssr-outlet-->占位符,本例子在div#root里写入:<div id="root"><!--vue-ssr-outlet--></div>

最后执行node skeleton就能实现vue的骨架屏。
最终的index.html:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><title>Document</title>
<style data-vue-ssr-id="a7049cb4:0">
.skeleton[data-v-61761ff8] {position: relative;height: 100%;overflow: hidden;padding: 15px;box-sizing: border-box;background: #fff;
}
.skeleton-nav[data-v-61761ff8] {height: 45px;background: #eee;margin-bottom: 15px;
}
.skeleton-swiper[data-v-61761ff8] {height: 160px;background: #eee;margin-bottom: 15px;
}
.skeleton-tabs[data-v-61761ff8] {list-style: none;padding: 0;margin: 0 -15px;display: flex;flex-wrap: wrap;
}
.skeleton-tabs-item[data-v-61761ff8] {width: 25%;height: 55px;box-sizing: border-box;text-align: center;margin-bottom: 15px;
}
.skeleton-tabs-item span[data-v-61761ff8] {display: inline-block;width: 55px;height: 55px;border-radius: 55px;background: #eee;
}
.skeleton-banner[data-v-61761ff8] {height: 60px;background: #eee;margin-bottom: 15px;
}
.skeleton-productions[data-v-61761ff8] {height: 20px;margin-bottom: 15px;background: #eee;
}
</style></head>
<body><div id="root"><div data-server-rendered="true" class="skeleton page" data-v-61761ff8><div class="skeleton-nav" data-v-61761ff8></div> <div class="skeleton-swiper" data-v-61761ff8></div> <ul class="skeleton-tabs" data-v-61761ff8><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li><li class="skeleton-tabs-item" data-v-61761ff8><span data-v-61761ff8></span></li></ul> <div class="skeleton-banner" data-v-61761ff8></div> <div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div><div class="skeleton-productions" data-v-61761ff8></div></div></div>
</body>
</html>

尾声

文章开头小米商城手机页面就是用的这样的方法,不同的是它的骨架屏是一个base64的图片。

更多关于vue-server-renderer内容请戳vue-ssr
相关demo
转载自https://segmentfault.com/a/1190000014963269

转载于:https://www.cnblogs.com/hongsusu/p/9439152.html

Vue页面骨架屏(一)相关推荐

  1. Vue 实现骨架屏(skeleton)

    Vue实现骨架屏的步骤: 1.安装骨架屏插件: npm install vue-skeleton-webpack-plugin 2.由于骨架屏插件依赖服务端渲染,再安装vue-server-rende ...

  2. vue页面白屏的原因及优化

    一.原因: 单页面应用的 html 是靠 js 生成,因为首屏需要加载很大的js文件(app.js 和vendor.js),所以当网速差的时候会产生一定程度的白屏 二.解决办法: 1.路由懒加载,组件 ...

  3. 【骨架屏】【vue】如何在webpack+vue+vue-cli下搭建多模块/单模块多路由骨架屏

    如何在webpack+vue+vue-cli下搭建多模块/单模块多路由骨架屏 前言 骨架屏的用户感知比loading更好,此前看过很多专栏以及文章,此次实践中还是遇到需要学习的部分. 对于骨架屏或者占 ...

  4. vue骨架屏实现方式(转载,作者:jrainlau)

    Vue 页面骨架屏注入实践 作者:jrainlau segmentfault.com/a/1190000014832185 作为与用户联系最为密切的前端开发者,用户体验是最值得关注的问题.关于页面lo ...

  5. (亲测)vue-cli项目添加骨架屏多种方式,自动生成骨架屏

    vue-cli项目首页加载缓慢想要使用骨架屏效果,经过几天的踩坑,这里学习并记录一下vue项目自动生成骨架屏方法. 添加骨架屏,其优势在于: 写于HTML文件中,独立于Vue框架,节省了JS加载时间+ ...

  6. 一种自动化生成骨架屏的方案

    今天分享的主题是:「一种自动化生成骨架屏的方案」, 先看下市场上常见的骨架屏优化效果. 今天的分享主要分为三个部分: 首屏加载状态演进 如何构建骨架屏 将骨架屏打包的项目中 首屏加载的演进 我们先来看 ...

  7. 骨架屏 之 Vue SSR(快捷简易版本解决方案)

    一. 骨架屏简介 简单来说, 骨架屏就是填充了背景等特效的真实页面手稿轮廓图. 它可以是精确/粗略的描述了页面各个元素大小,形状,位置占位的一种页面真实数据渲染加载前的排版. 目的是加载页面过程中给用 ...

  8. react骨架屏自动生成_用纯 DOM 的方式结合 Puppeteer 自动生成网页骨架屏

    骨架屏是在页面数据尚未加载完成前先给用户展示出页面的大致结构,直到请求数据返回后再显示真正的页面内容:随着单页应用( SPA )的越来越流行,单页应用的用户体验也越来越得到前端开发者的关注:为了优化用 ...

  9. 使用 Vite 插件自动化实现骨架屏

    大厂技术  高级前端  Node进阶 点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 作者:橙红年代 原文:https://juejin.cn/post/715240673710 ...

最新文章

  1. 求两个矩形重叠部分的面积
  2. 别说,Cerebro还真好用!老板再也不用担心ES集群了
  3. Invoke shell in Java
  4. window.location跳转页面
  5. 使用snmp4j实现Snmp功能(一)
  6. 我的探究:为什么.h头文件中不要写using namespace std
  7. Mapreduce的序列化和流量统计程序开发
  8. 了解 DB2 Version 9.5 中的全局变量(转)
  9. 关于 matlab 的 s 函数的 DirFeedthrough
  10. 论计算机专业毕业生的人文素养
  11. stm32中断优先级_浅谈STM32串口USART1的使用
  12. 自己做量化交易软件(28)小白量化实战2--变红买入变绿卖出
  13. 幸运抽奖系统带后台源码
  14. qq出示测试软件语音聊天,腾讯qq语音聊天麦克风的[qq语音语音测试]解决方案
  15. PHP通过推广二维码追溯统计用户来源
  16. 微信小程序实现替换logo功能
  17. python3遍历目录查找文件
  18. 认识java安全管理器SecurityManager
  19. Linux 文件的加密解密
  20. 百度质量部面试体验之 三面

热门文章

  1. Oracle 数据库的替代变量问题(即 set define off/on 的用法)
  2. 常州全国计算机考点,2017年常州高考考点及考场查询系统
  3. linux pdb创建表空间,ORACLE12C PDB创建默认表空间和用户语句(示例代码)
  4. 滴滴java开发面试题_Java开发经典面试题(十二)
  5. 计算机控制cs,计算机控制
  6. python举两种字符串引号的例子_python里的单引号和双引号的有什么作用
  7. linux 命令 ppt,Linux基本命令()讲解.ppt
  8. php7设置最大连接数,sybase 15.7 修改 number of user connections 最大连接数
  9. 计算机网络整体框架理解与把握(持续更新)
  10. pat 乙级 1011 A+B 和 C(C++)