在页面初始时没有加载出来,页面显示一片空白,永不体验不好,就可以使用骨架屏,就是在页面内容还未加载完成的时候,先让一些图片或者固定结构站位,
待内容加载完成之后把他替换掉
思路:
webpack中最终生成的html页面使用的是html-webpack-plugin插件,它提供了一系列的事件,我们可以注册到他处理html之前,使用html-webpack-plugin-before-html-processing事件把骨架屏动态插入进去;
插件:plugin.js
骨架屏的代码:
<div id="app">
<div style="100%;height:50px;background: rgb(211, 219, 224);"></div>
<ul class="loading-skeleton" style="">
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
</ul>
<style>
.loading-skeleton{
100%;height:auto;list-style: none;overflow: hidden;margin:0;padding:0;
}
.loading-skeleton li{
40%;
height: 180px;
float: left;
margin: 3% 7% 3% 3%;
}
.loading-skeleton li .d1{
100%;
height: 130px;
background: rgb(211, 219, 224);
}
.loading-skeleton li .d2{
100%;
height: 15px;
background: rgb(211, 219, 224);
margin-top: 5px;
}
.loading-skeleton .o {
float:left;92%;height:100px;margin:3%;
background: rgb(211, 219, 224);
animation: skeleton-stripes 1s linear infinite;
transform-origin: left;
animation: skeleton-stretch .5s linear infinite alternate;
}
.loading-skeleton .d {
float:left;92%;height:100px;margin:3%;
background: rgb(211, 219, 224);
animation: skeleton-stripes 1s linear infinite;
transform-origin: left;
animation: skeleton-stretch .5s -.5s linear infinite alternate;
}
@keyframes skeleton-stretch {
from {
transform: scalex(1);
}
to {
transform: scalex(.3);
}
}
</style>
</div>
效果:

插件plugin.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
class MyPlugin_skeleton {
constructor(options) {
this.options = options;
}
apply(compiler) {
compiler.hooks.compilation.tap('MyPlugin', (compilation) => {
// //编译之前,生成一个text.txt文件,通过compilation操作文件,只是演示与骨架屏没有关系,本身是node环境,根据node+fs也可以使用
console.log(this.options);
compilation.assets['./text.txt'] = {
source: () => this.options.text,
size: () => this.options.text.length
};
HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync('MyPlugin',
(data, cb) => {
////在编译html文件之前把骨架屏动态加入进去
data.html = data.html.replace('<div id="app"></div>', `这里是骨架屏代码`);
//错误优先原则,如果处理有错误,传递到第一个参数,否则参数的位置就null
cb(null, data) //重点,一定要有回调函数,否则内容不会生效
}
)
})
}
}
module.exports = MyPlugin_skeleton;
在webpack.prod.conf.js中引入插件,并使用,它是根据HtmlWbpackPlugin提供的一个口子来处理,插件需要安装在htmlwebapckplugin下面


打包项目 npm run build
打开dist/index.html 可以看到我们的骨架屏已经插入到root中
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>index</title>
<link href="static/css/main.css" rel="stylesheet">
</head>
<body>
<div id="app">
<div style="100%;height:50px;background: rgb(211, 219, 224);"></div>
<ul class="loading-skeleton" style="">
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
<li>
<div class="d1"></div>
<div class="d2 o"></div>
<div class="d2 d"></div>
</li>
</ul>
<style>
.loading-skeleton {
100%;
height: auto;
list-style: none;
overflow: hidden;
margin: 0;
padding: 0;
}
.loading-skeleton li {
40%;
height: 180px;
float: left;
margin: 3% 7% 3% 3%;
}
.loading-skeleton li .d1 {
100%;
height: 130px;
background: rgb(211, 219, 224);
}
.loading-skeleton li .d2 {
100%;
height: 15px;
background: rgb(211, 219, 224);
margin-top: 5px;
}
.loading-skeleton .o {
float: left;
92%;
height: 100px;
margin: 3%;
background: rgb(211, 219, 224);
animation: skeleton-stripes 1s linear infinite;
transform-origin: left;
animation: skeleton-stretch .5s linear infinite alternate;
}
.loading-skeleton .d {
float: left;
92%;
height: 100px;
margin: 3%;
background: rgb(211, 219, 224);
animation: skeleton-stripes 1s linear infinite;
transform-origin: left;
animation: skeleton-stretch .5s -.5s linear infinite alternate;
}
@keyframes skeleton-stretch {
from {
transform: scalex(1);
}
to {
transform: scalex(.3);
}
}
</style>
</div>
<script src="static/js/main.c43cd934e03c41d9a79f.js"></script>
</body>
</html>
这是一个通用的骨架屏模板,也可以根据自己的需求,设置不同的骨架屏
拓展
其实还可以根据用户访问路径进行打包不同的骨架,无非就加入path判断,塞入不同样式。
var hash=window.location.hash;
var path=window.location.pathname;
根据path不同,显示不同的骨架屏