github地址:VV-UI/VV-UIdemo地址:vv-ui文档地址:skeletonAbout骨架屏介绍骨架屏的作用主要是在网络请求时提供一个基本的占位符比较慢,当数据加载完成后,恢复数据显示。这会给用户一个自然的过渡,而不会导致页面长时间空白或闪烁。常见的骨架屏实现有ssr服务端渲染和prerender。这里主要是通过代码一步一步来展示如何制作这样一个骨架屏:prerender渲染骨架屏这个组件库中骨架屏的实现也是基于预渲染的。更详细的预渲染介绍可以参考这篇文章:另一种处理Vue单页MetaSEO的方法。下面介绍一下它的实现步骤。首先,我们还需要配置webpack-plugin,但是已经有一个prerender-spa-plugin可用。varpath=require('path')varPrerenderSpaPlugin=require('prerender-spa-plugin')module.exports={//...plugins:[newPrerenderSpaPlugin(//已编译SPA的绝对路径path.join(__dirname,'../dist'),//预渲染路由列表['/'])]}然后编写我们的骨架屏文件main.skeleton.vue</div>第一次进入页面时,我们需要展示骨架屏。数据加载完成后,我们需要移除骨架屏:ssr渲染骨架屏下面我用我灵魂画家的笔触画出大概的流程:首先createourskeleton.entry.jsimportVuefrom'vue';importSkeletonfrom'./skeleton.vue';exportdefaultnewVue({components:{Skeleton},模板:'<骨架/>'});当然这里的skeleton.vue可以让我们提前写好骨架屏组件可能是这样的:那么我们需要的是能够将skeleton.entry.js编译成服务端渲染可用的bundle文件,所以我们需要一个编译骨架屏幕的webpack.ssr.conf.js文件:constpath=require('path');constmerge=require('webpack-merge');constbaseWebpackConfig=require('./webpack.base.conf');constnodeExternals=require('webpack-node-externals');functionresolve(dir){returnpath.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渲染bundle,最终产生对应的html片段和css片段。这是核心代码://webpack开始工作varserverCompiler=webp确认(服务器WebpackConfig);varmfs=newMFS();//输出到mfsserverCompiler.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);});varbundle=mfs.readFileSync(outputPath,'utf-8');varskeletonCss=mfs.readFileSync(outputCssPath,'utf-8');//使用bundle创建渲染器varrenderer=createBundleRenderer(bundle);//使用vuessr渲染骨架renderer.renderToString({},function(err,skeletonHtml){if(err){reject(err);}else{resolve({skeletonHtml:skeletonHtml,skeletonCss:skeletonCss});}});});最后一步,我我们将输出的html片段和css片段组合起来生成最终的html,所以我们需要在webpack编译和挂载之前监听事件:compiler.plugin('compilation',function(compilation){//为html-webpack添加监听器-plugincompilation.plugin('html-webpack-plugin-before-html-processing',function(htmlPluginData,callback){ssr(webpackConfig).then(function(ref){varskeletonHtml=ref.skeletonHtml;varskeletonCss=ref.skeletonCss;//在html中插入内联样式varheadTagEndPos=htmlPluginData.html.lastIndexOf('');htmlPluginData.html=insertAt(htmlPluginData.html,(""),headTagEndPos);//在html中用ssr结果替换挂载点varappPos=htmlPluginData.html.lastIndexOf(insertAfter)+insertAfter.length;htmlPluginData.html=insertAt(htmlPluginData.html,skeletonHtml,appPos);callback(空,htmlPluginData);});});});简介:作者:monkeyWang本文参考文章:vue项目添加骨架屏详见本文源码:VV-UI/VV-UI我的主页:monkeyWang微信公众号:前端知识铺会推送前端技术不定期文章,欢迎关注