Vue页面骨架屏(一)
在開發(fā)webapp的時候總是會受到首屏加載時間過長的影響,主流的解決方法是在載入完成之前顯示loading圖效果,而一些大公司會配置一套服務(wù)端渲染的架構(gòu)來解決這個問題。考慮到ssr所要解決的一系列問題,越來越多的APP采用了“骨架屏”的方式去提升用戶體驗。
一、分析Vue頁面的內(nèi)容加載過程
vue項目中的入口index.html只有簡單的內(nèi)容:
<!DOCTYPE html> <html lang="zh-CN"> <head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><title>Document</title> </head> <body><div id="root"> </div><script type="text/javascript" src="bundle.js"></script></body> </body> </html>當(dāng)js執(zhí)行完之后,會用vue渲染成的dom將div#root完全替換掉。
我們在div#root中加入模擬骨架屏,在Chrome開發(fā)者工具調(diào)整網(wǎng)速:
?
由此可知,將骨架屏內(nèi)容直接插入div#root中即可實現(xiàn)骨架屏。
二、使用vue-server-renderer來實現(xiàn)骨架屏
我們需要骨架屏也是一個單獨的.vue文件,因此我們需要用到vue-server-renderer。對vue服務(wù)端渲染有所了解的同學(xué)一定知道,這個插件能夠?qū)ue項目在node端打包成一個bundle,然后由bundle生成對應(yīng)的html。
首先是生成項目:
vue的服務(wù)端渲染一般會用vue-server-renderer將整個項目在node端打包成一份bundle,而這里我們只要一份有骨架屏的html,所以會有一個單獨的骨架屏入口文件skeleton-entry.js,一個骨架屏打包webpack配置webpack.config.server.js,而skeleton.js作用是將webpack打包出來的bundle寫入到index.html中。
//skeleton-entry.js import Vue from 'vue' import Skeleton from './views/skeleton/skeleton.vue'export default new Vue({components: {Skeleton},template: '<skeleton />' }) //webpack.config.server.js const path = require('path') const { VueLoaderPlugin } = require('vue-loader') const VueSSRServerPlugin = require('vue-server-renderer/server-plugin')module.exports = {mode: process.env.NODE_ENV,target: 'node',entry: path.join(__dirname, '../src/skeleton-entry.js'),output: {path: path.join(__dirname, '../server-dist'),filename: 'server.bundle.js',libraryTarget: 'commonjs2'},module: {rules: [{test: /\.vue$/,loader: 'vue-loader'},{test: /\.css$/,use: ['vue-style-loader','css-loader']} ]},externals: Object.keys(require('../package.json').dependencies),resolve: {alias: {'vue$': 'vue/dist/vue.esm.js'}},plugins: [new VueLoaderPlugin(),new VueSSRServerPlugin({filename: 'skeleton.json'})] }其中骨架屏的webpack配置因為是node端,所以需要target: 'node' libraryTarget: 'commonjs2'。在VueSSRServerPlugin中,指定了其輸出的json文件名。當(dāng)執(zhí)行webpack會在/server-dist目錄下生成一個skeleton.json文件,這個文件記載了骨架屏的內(nèi)容和樣式,會提供給vue-server-renderer使用。
//skeleton.js const fs = require('fs') const path = require('path')const createBundleRenderer = require('vue-server-renderer').createBundleRenderer// 讀取`skeleton.json`,以`index.html`為模板寫入內(nèi)容 const renderer = createBundleRenderer(path.join(__dirname, './server-dist/skeleton.json'), {template: fs.readFileSync(path.join(__dirname, './index.html'), 'utf-8') })// 把上一步模板完成的內(nèi)容寫入(替換)`index.html` renderer.renderToString({}, (err, html) => {fs.writeFileSync('index.html', html, 'utf-8') }) 注意,作為模板的html文件,需要在被寫入內(nèi)容的位置添加<!--vue-ssr-outlet-->占位符,本例子在div#root里寫入:<div id="root"><!--vue-ssr-outlet--></div>最后執(zhí)行node skeleton就能實現(xiàn)vue的骨架屏。
最終的index.html:
尾聲
文章開頭小米商城手機(jī)頁面就是用的這樣的方法,不同的是它的骨架屏是一個base64的圖片。
更多關(guān)于vue-server-renderer內(nèi)容請戳vue-ssr
相關(guān)demo
轉(zhuǎn)載自https://segmentfault.com/a/1190000014963269
轉(zhuǎn)載于:https://www.cnblogs.com/hongsusu/p/9439152.html
總結(jié)
以上是生活随笔為你收集整理的Vue页面骨架屏(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 列表与for循环
- 下一篇: Vue(二十八)el-cascader