开发一个简单易懂的webpack骨架屏插件

1,709 阅读3分钟

一、骨架屏的由来:

单页面应用在现在的前端页面开发是越来越常见了。
它的好处很多,坏处也很明显:就是首屏加载往往很慢,呈现一片空白的页面,这给用户的体验感是很差的。
可资源的加载我们除了尽量地优化,也没有其他很好的办法了。为了解决这个体验感的问题,骨架屏应运而生。

二、骨架屏原理:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>skeleton-plugin</title>
  <style></style>
</head>
<body>
    <div id="root"></div>
</body>
</html>

单页面应用其实就是一个html文件,html结构里面有一个div#root,当js加载完毕并且执行完成后,id为root的div会被整个替换掉。所以由此我们可以想到,我们在div#root里面写一些动画之类的html结构,在js没有加载完成的时候,让用户看到的不是一片空白,而是预先写好的骨架页面。这样的体验感是不是会好一点呢。

三、webpack插件的编写:

(1)webpack插件介绍

首先得构建一个简单的webpack项目(这个过程不详细说了)。在根目录下新建一个skeleton-plugin.js文件。由于我们需要在每次打包的时候都重新生成新的骨架屏的index.html文件,所以这里需要用到html-webpack-plugin插件。我们在skeleton-plugin.js插件注入html-webpack-plugin插件的监听器,在html-webpack-plugin插件生成index.html之前做骨架屏代码的插入。

在此之前。我们需要了解一下webpack得plugin编写知识。下图是截于官方的一段话:(www.webpackjs.com/contribute/…

(2)但插件的具体实现

由此可以知道,我们的骨架屏插件要有一个apply的方法,在安装插件时,会被webpack compiler 调用一次。 该apply方法传入compiler参数,该参数暴露了webpack生命周期钩子函数供开发者使用,我们可以使用它来访问 webpack 的主环境。使用方法为:compiler.hooks.钩子函数名称.tap(...)。

//skeleton-plugin.js
//引入html-webpack-plugin插件
const HtmlWebpackPlugin = require('html-webpack-plugin');

//创建一个SkeletonPlugin类
class SkeletonPlugin {

  apply (compiler) {
  
    //我们这里监听compilation钩子函数,目的是编译创建之后,执行我们的SkeletonPlugin插件的主要代码
    compiler.hooks.compilation.tap('SkeletonPlugin', (compilation) => {
    
      //在html-webpack-plugin插件生成资源到output目录之前,我们完成对骨架屏代码的插入
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'SkeletonPlugin',
        (htmlData, cb) => {
        
          //我们在这个回调中做骨架屏代码的插入
          //htmlData.html是html-webpack-plugin插件的template模板解析后的字符串
          //在输出index.html之前,我们将template模板里的<div id="root"></div>替换成骨架屏代码。
          htmlData.html = htmlData.html.replace(
          '<div id="root"></div>',
          `<div id="root">
              <div style="background-color:red;height:300px;display:none;" id="default" >
                  我是骨架屏页面
              </div>
          </div>`);
        
        //最后执行cb回调,告诉webpack,我们的插件已经操作完成,让它继续执行其他的操作
        cb(null, htmlData)
        }
      )
    });
  }
}
//导出SkeletonPlugin插件
module.exports = SkeletonPlugin;

(3)插件的使用

最后在webpack的配置文件webpack.config.js里写上以下代码:

  plugins: [
    new HtmlWebpackPlugin({
        //index.html模板位置,上面代码中出现的htmlData.html就是这个模板解析后的内容。
        template: './public/index.html',
        inject: 'body',
    }),
    new SkeletonPlugin(),
  ]

当webpack打包成功后,dist文件夹下的index.html将变成下图所示:

四、结束语:

到这里简单的骨架屏插件就完成了。但这个插件只会在首次加载页面的时候有骨架屏效果。对于其他页面是没有效果的。

下篇文件将介绍《多页面的骨架屏插件》的编写思路。

(如有错误的内容请大家多多包涵,谢谢)