给Vue集成Skeleton骨架屏,并加持PWA
背景
这几天刚了解了PWA,但是实际项目受限于基础环境(https)无法快速落地,找来Vue这个Demo项目,再整理一下,为后面实际落地做准备。
玩法
基于Vue-cli创建的项目,加入Skeleton和PWA属性,升级Demo项目
步骤
- 通过Vue-cli搭建Vue项目
- 加持PWA
- 加入Skeleton
步骤一:搭建Vue项目
通过Vue官网资源,通过Vue-cli搭建Vue项目说明应该还是很详细的,这里不在赘述。
注意需要手动安装“prettier”
npm install prettier@1.12.0
步骤二:加持PWA
Vue对自己的定义同样包含“渐进式”JavaScript框架,所以应该和PWA还是蛮般配的。
通过Google提供的PWA开发继承工具Workbox,可以快速给我们的应用加持PWA:
1. 安装依赖
# 项目添加workbox-webpack-plugin组件
npm install --save-dev workbox-webpack-plugin
# 项目添加sw-register-webpack-plugin组件
npm install --save-dev sw-register-webpack-plugin
2. 在webpack中引用插件,并设置配置信息
// webpack.dev.conf.js、webpack.prod.conf.js webpack配置文件添加插件配置
const WorkBoxPlugin = require('workbox-webpack-plugin')
const SwRegisterWebpackPlugin = require('sw-register-webpack-plugin')
// 以service-worker.js文件为模板,注入生成service-worker.js
new WorkBoxPlugin.InjectManifest({
swSrc: path.resolve(__dirname, '../src/service-worker.js')
}),
// 通过插件注入生成sw注册脚本
new SwRegisterWebpackPlugin({
version: +new Date()
}),
3. workbox(service-worker)配置,主要是局部缓存策略
// 启动后停止旧的sw
workbox.skipWaiting()
workbox.clientsClaim()
// 设置缓存名称前缀
workbox.core.setCacheNameDetails({
prefix: 'vuecli'
})
// 缓存manifest.json
workbox.routing.registerRoute(
/\/manifest\.json/,
workbox.strategies.staleWhileRevalidate()
)
// sw-register网络请求优先
workbox.routing.registerRoute(
/\/sw-register\.js/,
workbox.strategies.networkOnly()
)
workbox.precaching.precacheAndRoute(self.__precacheManifest || [])
上面几步就完成了!信不信?就是这么easy!
步骤三:加入Skeleton
Skeleton,骨架屏,在页面数据尚未加载前先给用户展示出页面的大致结构,直到请求数据返回后再渲染页面,补充进需要显示的数据内容,一般用于首页、数据列表等。
我们可以通过vue-skeleton-webpack-plugin快速实现骨架屏的搭建
1. 安装vue-skeleton-webpack-plugin
npm install --save-dev vue-skeleton-webpack-plugin
2. 添加Skeleton.vue骨架页面
<template>
<div class="skeleton-wrapper">
<header class="skeleton-header"></header>
<section class="skeleton-block">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMTA4MCAyNjEiPjxkZWZzPjxwYXRoIGlkPSJiIiBkPSJNMCAwaDEwODB2MjYwSDB6Ii8+PGZpbHRlciBpZD0iYSIgd2lkdGg9IjIwMCUiIGhlaWdodD0iMjAwJSIgeD0iLTUwJSIgeT0iLTUwJSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94Ij48ZmVPZmZzZXQgZHk9Ii0xIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlQ29sb3JNYXRyaXggaW49InNoYWRvd09mZnNldE91dGVyMSIgdmFsdWVzPSIwIDAgMCAwIDAuOTMzMzMzMzMzIDAgMCAwIDAgMC45MzMzMzMzMzMgMCAwIDAgMCAwLjkzMzMzMzMzMyAwIDAgMCAxIDAiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDEpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGw9IiNGRkYiIHhsaW5rOmhyZWY9IiNiIi8+PHBhdGggZmlsbD0iI0Y2RjZGNiIgZD0iTTIzMCA0NGg1MzN2NDZIMjMweiIvPjxyZWN0IHdpZHRoPSIxNzIiIGhlaWdodD0iMTcyIiB4PSIzMCIgeT0iNDQiIGZpbGw9IiNGNkY2RjYiIHJ4PSI0Ii8+PHBhdGggZmlsbD0iI0Y2RjZGNiIgZD0iTTIzMCAxMThoMzY5djMwSDIzMHpNMjMwIDE4MmgzMjN2MzBIMjMwek04MTIgMTE1aDIzOHYzOUg4MTJ6TTgwOCAxODRoMjQydjMwSDgwOHpNOTE3IDQ4aDEzM3YzN0g5MTd6Ii8+PC9nPjwvc3ZnPg==">
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMTA4MCAyNjEiPjxkZWZzPjxwYXRoIGlkPSJiIiBkPSJNMCAwaDEwODB2MjYwSDB6Ii8+PGZpbHRlciBpZD0iYSIgd2lkdGg9IjIwMCUiIGhlaWdodD0iMjAwJSIgeD0iLTUwJSIgeT0iLTUwJSIgZmlsdGVyVW5pdHM9Im9iamVjdEJvdW5kaW5nQm94Ij48ZmVPZmZzZXQgZHk9Ii0xIiBpbj0iU291cmNlQWxwaGEiIHJlc3VsdD0ic2hhZG93T2Zmc2V0T3V0ZXIxIi8+PGZlQ29sb3JNYXRyaXggaW49InNoYWRvd09mZnNldE91dGVyMSIgdmFsdWVzPSIwIDAgMCAwIDAuOTMzMzMzMzMzIDAgMCAwIDAgMC45MzMzMzMzMzMgMCAwIDAgMCAwLjkzMzMzMzMzMyAwIDAgMCAxIDAiLz48L2ZpbHRlcj48L2RlZnM+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwIDEpIj48dXNlIGZpbGw9IiMwMDAiIGZpbHRlcj0idXJsKCNhKSIgeGxpbms6aHJlZj0iI2IiLz48dXNlIGZpbGw9IiNGRkYiIHhsaW5rOmhyZWY9IiNiIi8+PHBhdGggZmlsbD0iI0Y2RjZGNiIgZD0iTTIzMCA0NGg1MzN2NDZIMjMweiIvPjxyZWN0IHdpZHRoPSIxNzIiIGhlaWdodD0iMTcyIiB4PSIzMCIgeT0iNDQiIGZpbGw9IiNGNkY2RjYiIHJ4PSI0Ii8+PHBhdGggZmlsbD0iI0Y2RjZGNiIgZD0iTTIzMCAxMThoMzY5djMwSDIzMHpNMjMwIDE4MmgzMjN2MzBIMjMwek04MTIgMTE1aDIzOHYzOUg4MTJ6TTgwOCAxODRoMjQydjMwSDgwOHpNOTE3IDQ4aDEzM3YzN0g5MTd6Ii8+PC9nPjwvc3ZnPg==">
</section>
</div>
</template>
<script>
export default {
name: 'skeleton'
}
</script>
<style scoped>
.skeleton-header {
height: 152px;
background: grey;
margin-top: 60px;
width: 152px;
margin: 60px auto;
}
.skeleton-block {
display: flex;
flex-direction: column;
padding-top: 8px;
}
</style>
3. 添加骨架屏入口entry-skeleton.js
import Vue from 'vue'
import Skeleton from './components/Skeleton'
export default new Vue({
components: {
Skeleton
},
template: '<skeleton />'
})
4. webpack中加入skeleton打包插件
new SkeletonWebpackPlugin({
webpackConfig: require('./webpack.skeleton.conf')
})
参考文档:
示例代码:
追加一点修改:vue-skeleton-webpack-plugin支持多页面多骨架屏的配置,具体配置如下:
// webpack配置中
new SkeletonWebpackPlugin({
webpackConfig: require('./webpack.skeleton.conf'),
router: {
mode: 'hash',
routes: [
{
path: '/',
skeletonId: 'skeleton'
},
{
path: '/detail',
skeletonId: 'skeleton_detail'
}
]
}
})
对应的页面就需要有多个骨架屏页面,只需要修改entry-skeleton文件即可:
export default new Vue({
components: {
Skeleton,
SkeletonDetail
},
// 多骨架屏从实现上看,实际上是把多个骨架屏都加载到页面上
// 然后通过webpackconfig中的routes配置的skeletonId确定显示某一个skeleton
template: `
<div>
<skeleton id="skeleton" style="display:none"/>
<skeletonDetail id="skeleton_detail" style="display:none"/>
</div>
`
})
编辑于 2018-05-31 13:32