一、page-skeleton-webpack-plugin
page-skeleton-webpack-plugin是一款由ElemeFE团队开发的webpack 插件,该插件的目的是根据你项目中不同的路由页面生成相应的骨架屏页面,并将骨架屏页面通过 webpack 打包到对应的静态路由页面中。
二、插件自动生成骨架屏的主要原理
- 通过无头浏览器puppeteer打开要生成骨架屏的页面
- 等待页面渲染完后注入提取骨架屏的脚本(注意:一定要等页面完全渲染完,不然提取的DOM不完整)
- 对页面中元素进行删减或增添,对已有元素通过层叠样式进行覆盖,这样达到在不改变页面布局下,隐藏图片和文字,通过样式覆盖,使得其展示为灰色块。然后将修改后的 HTML 和 CSS 样式提取出来生成骨架屏。
先demo展示一下如何自动生成骨架屏,后续再通过代码具体分析如何生成骨架屏:
安装运行环境
依赖环境:
- puppeteer
- nodejs v8.x
安装puppeteer可参考:
www.jianshu.com/p/a9a55c03f…
启动puppeteer并打开要生成骨架屏的页面
const puppeteer = require('puppeteer');
const devices = require('puppeteer/DeviceDescriptors');
const iPhone = devices['iPhone 6'];
const { Skeleton } = require('page-skeleton-webpack-plugin');
let skeleton = new Skeleton();
(async () => {
const browser = await (puppeteer.launch({
//设置超时时间
timeout: 15000,
//如果是访问https页面 此属性会忽略https错误
ignoreHTTPSErrors: true,
// 打开开发者工具, 当此值为true时, headless总为false
devtools: true,
// 非headless模式,为了能直观看到页面生成骨架屏的过程
headless: false
}));
const page = await browser.newPage();
// 因为是移动端,设置模拟iphone6
await page.emulate(iPhone);
// 打开m站首页
await page.goto('https://m.to8to.com/sz');
// 等待首屏bannar加载完成
await page.waitForSelector('.ad-data-report-carousel');
// 开始build骨架屏
await skeleton.makeSkeleton(page);
})();
复制代码
接下来分析makeSkeleton是如何生成骨架屏代码
入口代码在
page-skeleton-webpack-plugin/src/skeleton.js
- 通过page.addScriptTag向puppeteer注入脚本并初始化,脚本路径在page-skeleton-webpack-plugin/src/script/index.js。
- 执行genSkeleton方法生成骨架屏
async makeSkeleton(page) {
const {defer} = this.options
// 把生成骨架屏代码注入puppeteer同时执行初始化
await page.addScriptTag({
content: this.scriptContent})
// 延迟逻辑,用于等待某些异步操作,图1我已经使用waitForSelector,所以这个可以不用管
await sleep(defer)
// 执行genSkeleton方法
await page.evaluate((options) => {
Skeleton.genSkeleton(options)
}, this.options)
}
复制代码
初始化核心逻辑:
- 初始化参数说明:
const pluginDefaultConfig = {
port: '8989',
// 该配置对象可以配置一个 color 字段,用于决定骨架页面中文字块的的颜色,颜色值支持16进制、RGB等。
text: {
color: '#EEEEEE'
},
// 该配置接受 3 个字段,color、shape、shapeOpposite。color 和 shape 用于确定骨架页面中图片块的颜色和形状,
// 颜色值支持16 进制和 RGB等,形状支持两个枚举值,circle (矩形)和 rect(圆形)。
// shapeOpposite 字段接受一个数组,数组中每个元素是一个 DOM 选择器,用于选择 DOM 元素,
// 被选择 DOM 的形状将和配置的 shape 形状相反,例如,配置的是 rect那么,
// shapeOpposite 中的图片块将在骨架页面中显示成 circle 形状(圆形),具体怎么配置可以参考该部分末尾的默认配置。
image: {
shape: 'rect&