在开发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="/UploadFiles/2021-04-02/bundle.js">当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.jsonvue的服务端渲染一般会用
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文章相关代码已经同步到Github,欢迎查阅~
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新动态
- 雨林唱片《赏》新曲+精选集SACD版[ISO][2.3G]
- 罗大佑与OK男女合唱团.1995-再会吧!素兰【音乐工厂】【WAV+CUE】
- 草蜢.1993-宝贝对不起(国)【宝丽金】【WAV+CUE】
- 杨培安.2009-抒·情(EP)【擎天娱乐】【WAV+CUE】
- 周慧敏《EndlessDream》[WAV+CUE]
- 彭芳《纯色角3》2007[WAV+CUE]
- 江志丰2008-今生为你[豪记][WAV+CUE]
- 罗大佑1994《恋曲2000》音乐工厂[WAV+CUE][1G]
- 群星《一首歌一个故事》赵英俊某些作品重唱企划[FLAC分轨][1G]
- 群星《网易云英文歌曲播放量TOP100》[MP3][1G]
- 方大同.2024-梦想家TheDreamer【赋音乐】【FLAC分轨】
- 李慧珍.2007-爱死了【华谊兄弟】【WAV+CUE】
- 王大文.2019-国际太空站【环球】【FLAC分轨】
- 群星《2022超好听的十倍音质网络歌曲(163)》U盘音乐[WAV分轨][1.1G]
- 童丽《啼笑姻缘》头版限量编号24K金碟[低速原抓WAV+CUE][1.1G]