资讯专栏INFORMATION COLUMN

Vue单页面骨架屏实践

DevTTL / 1009人阅读

github 地址: VV-UI/VV-UI

演示地址: vv-ui

文档地址:skeleton

关于骨架屏介绍

骨架屏的作用主要是在网络请求较慢时,提供基础占位,当数据加载完成,恢复数据展示。这样给用户一种很自然的过渡,不会造成页面长时间白屏或者闪烁等情况。 常见的骨架屏实现方案有ssr服务端渲染和prerender两种解决方案。这里主要通过代码为大家展示如何一步步做出这样一个骨架屏:

prerender 渲染骨架屏

本组件库骨架屏的实现也是基于预渲染去实现的,有关于预渲染更详细的介绍请参考这篇文章:处理 Vue 单页面 Meta SEO的另一种思路 下面我们主要介绍其实现步骤,首先我们也是需要配置webpack-plugin,不过已经有实现好的prerender-spa-plugin可用

var path = require("path")
var PrerenderSpaPlugin = require("prerender-spa-plugin")

module.exports = {
  // ...
  plugins: [
    new PrerenderSpaPlugin(
      // Absolute path to compiled SPA
      path.join(__dirname, "../dist"),
      // List of routes to prerender
      ["/"]
    )
  ]
} 

然后写好我们的骨架屏文件main.skeleton.vue

 

当初次进入页面的时候我们需要显示骨架屏,数据加载完,我们需要移除骨架屏:

 
ssr 渲染骨架屏

下面我用我灵魂画师的笔法,画出了大致的过程:

首先创建我们的skeleton.entry.js

import Vue from "vue";
import Skeleton from "./skeleton.vue";

export default new Vue({
    components: {
        Skeleton
    },
    template: ""
}); 

当然这里的skeleton.vue使我们事先写好的骨架屏组件,看起来可能是这样:

 

然后我们需要的是能把skeleton.entry.js编译成服务端渲染可用的bundle文件,所以我们需要有个编译骨架屏的webpack.ssr.conf.js文件:

const path = require("path");
const merge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.conf");
const nodeExternals = require("webpack-node-externals");

function resolve(dir) {
    return path.join(__dirname, dir);
}

module.exports = merge(baseWebpackConfig, {
    target: "node",
    devtool: false,
    entry: {
        app: resolve("./src/skeleton.entry.js")
    },
    output: Object.assign({}, baseWebpackConfig.output, {
        libraryTarget: "commonjs2"
    }),
    externals: nodeExternals({
        whitelist: /.css$/
    }),
    plugins: []
});

接下来最终的步骤,就是编写我们的webpackPlugin,我们期望我们的webpackPlugin可以帮我们把入口文件编译成bundle,然后再通过vue-server-renderer来render bundle,最终产出响应的html片段和css片段,这里贴出核心代码:

 // webpack start to work
    var serverCompiler = webpack(serverWebpackConfig);
    var mfs = new MFS();
    // output to mfs
    serverCompiler.outputFileSystem = mfs;
    serverCompiler.watch({}, function (err, stats) {

        if (err) {
            reject(err);
            return;
        }

        stats = stats.toJson();
        stats.errors.forEach(function (err) {
            console.error(err);
        });
        stats.warnings.forEach(function (err) {
            console.warn(err);
        });

        var bundle = mfs.readFileSync(outputPath, "utf-8");
        var skeletonCss = mfs.readFileSync(outputCssPath, "utf-8");
        // create renderer with bundle
        var renderer = createBundleRenderer(bundle);
        // use vue ssr to render skeleton
        renderer.renderToString({}, function (err, skeletonHtml) {
            if (err) {
                reject(err);
            }
            else {
                resolve({skeletonHtml: skeletonHtml, skeletonCss: skeletonCss});
            }
        });
    });

最后一步,我们对产出的html片段, css片段进行组装,产出最终的html,所以我们需要监听webpack 的编译挂载之前的事件:

compiler.plugin("compilation", function (compilation) {

    // add listener for html-webpack-plugin
    compilation.plugin("html-webpack-plugin-before-html-processing", function (htmlPluginData, callback) {
        ssr(webpackConfig).then(function (ref) {
            var skeletonHtml = ref.skeletonHtml;
            var skeletonCss = ref.skeletonCss;

            // insert inlined styles into html
            var headTagEndPos = htmlPluginData.html.lastIndexOf("");
            htmlPluginData.html = insertAt(htmlPluginData.html, (""), headTagEndPos);

            // replace mounted point with ssr result in html
            var appPos = htmlPluginData.html.lastIndexOf(insertAfter) + insertAfter.length;
            htmlPluginData.html = insertAt(htmlPluginData.html, skeletonHtml, appPos);
            callback(null, htmlPluginData);
        });
    });
 }); 
关于:

作者:monkeyWang

本文参考文章:为vue项目添加骨架屏

本文源码详见:VV-UI/VV-UI

本人主页:monkeyWang

微信公众号:前端知识铺
会不定期推送前端技术文章,欢迎关注

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/54507.html

相关文章

  • Vue页面骨架实践

    github 地址: VV-UI/VV-UI 演示地址: vv-ui 文档地址:skeleton 关于骨架屏介绍 骨架屏的作用主要是在网络请求较慢时,提供基础占位,当数据加载完成,恢复数据展示。这样给用户一种很自然的过渡,不会造成页面长时间白屏或者闪烁等情况。 常见的骨架屏实现方案有ssr服务端渲染和prerender两种解决方案。这里主要通过代码为大家展示如何一步步做出这样一个骨架屏: show...

    you_De 评论0 收藏0
  • Vue页面骨架实践

    github 地址: VV-UI/VV-UI 演示地址: vv-ui 文档地址:skeleton 关于骨架屏介绍 骨架屏的作用主要是在网络请求较慢时,提供基础占位,当数据加载完成,恢复数据展示。这样给用户一种很自然的过渡,不会造成页面长时间白屏或者闪烁等情况。 常见的骨架屏实现方案有ssr服务端渲染和prerender两种解决方案。这里主要通过代码为大家展示如何一步步做出这样一个骨架屏: show...

    233jl 评论0 收藏0
  • 骨架】【vue】如何在webpack+vue+vue-cli下搭建多模块/模块多路由骨架

    摘要:如何在下搭建多模块单模块多路由骨架屏前言骨架屏的用户感知比更好,此前看过很多专栏以及文章,此次实践中还是遇到需要学习的部分。包括因为可能信息面不全,对插件源码进行了详细解读,希望对于将要在项目中搭建骨架屏的小伙伴们有所帮助。 如何在webpack+vue+vue-cli下搭建多模块/单模块多路由骨架屏 前言 骨架屏的用户感知比loading更好,此前看过很多专栏以及文章,此次实践中还是...

    huhud 评论0 收藏0
  • 骨架】【vue】如何在webpack+vue+vue-cli下搭建多模块/模块多路由骨架

    摘要:如何在下搭建多模块单模块多路由骨架屏前言骨架屏的用户感知比更好,此前看过很多专栏以及文章,此次实践中还是遇到需要学习的部分。包括因为可能信息面不全,对插件源码进行了详细解读,希望对于将要在项目中搭建骨架屏的小伙伴们有所帮助。 如何在webpack+vue+vue-cli下搭建多模块/单模块多路由骨架屏 前言 骨架屏的用户感知比loading更好,此前看过很多专栏以及文章,此次实践中还是...

    MkkHou 评论0 收藏0
  • 前端骨架方案小结

    摘要:常用于文章列表动态列表页等相对比较规则的列表页面。很多项目中都有应用饿了么版本知乎等网站中都有应用。欢迎讨论,点个赞再走吧 骨架屏 最近在项目不时有用到骨架屏的需求,所以抽时间对骨架屏的方案作了一下调研,骨架屏的实践已经有很多了,也有很多人对自己的方案作了介绍.在这里按照个人的理解做了一个汇总和分类,分享给大家. 关于骨架屏(简介) 骨架屏就是在页面数据尚未加载前先给用户展示出页面的大...

    IntMain 评论0 收藏0

发表评论

0条评论

DevTTL

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<