webpack封裝插件實現骨架屏


在頁面初始時沒有加載出來,頁面顯示一片空白,永不體驗不好,就可以使用骨架屏,就是在頁面內容還未加載完成的時候,先讓一些圖片或者固定結構站位,

待內容加載完成之后把他替換掉

思路:

webpack中最終生成的html頁面使用的是html-webpack-plugin插件,它提供了一系列的事件,我們可以注冊到他處理html之前,使用html-webpack-plugin-before-html-processing事件把骨架屏動態插入進去;

插件:plugin.js

骨架屏的代碼:

<div id="app">
    <div style="width: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{
            width:100%;height:auto;list-style: none;overflow: hidden;margin:0;padding:0;
        }
        .loading-skeleton li{
            width: 40%;
            height: 180px;
            float: left;
            margin: 3% 7% 3% 3%;
        }
        .loading-skeleton li .d1{
            width: 100%;
            height: 130px;
            background: rgb(211, 219, 224);
        }
        .loading-skeleton li .d2{
            width: 100%;
            height: 15px;
            background: rgb(211, 219, 224);
            margin-top: 5px;
        }
        .loading-skeleton .o {
            float:left;width: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;width: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="width: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 {
                width: 100%;
                height: auto;
                list-style: none;
                overflow: hidden;
                margin: 0;
                padding: 0;
            }
            
            .loading-skeleton li {
                width: 40%;
                height: 180px;
                float: left;
                margin: 3% 7% 3% 3%;
            }
            
            .loading-skeleton li .d1 {
                width: 100%;
                height: 130px;
                background: rgb(211, 219, 224);
            }
            
            .loading-skeleton li .d2 {
                width: 100%;
                height: 15px;
                background: rgb(211, 219, 224);
                margin-top: 5px;
            }
            
            .loading-skeleton .o {
                float: left;
                width: 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;
                width: 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不同,顯示不同的骨架屏

 

參考1:https://www.jianshu.com/p/ec4bf33ab2c8

參考2:https://www.npmjs.com/package/html-webpack-plugin


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM