最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
详解如何在webpack中做预渲染降低首屏空白时间
时间:2022-06-25 15:44:12 编辑:袖梨 来源:一聚教程网
一、浏览器渲染过程
1、用户打开页面,空白屏,等待html的返回
2、html下载完毕,开始解析html,初始渲染
3、下载css、js等资源,执行js渲染虚拟DOM
4、发起请求、获取数据,渲染内容
下面我们主要是讨论一下如何通过预渲染的方式降低空白屏的时间
缩小首屏载时间是一个重要的优化项,总结来主要有以下几种方式:
1、尽可能的缩小webpack或者其他打包工具生成的包的大小
2、使用服务端渲染的方式
3、使用预渲染的方式
4、使用gzip减小网络传输的流量大小
5、按照页面或者组件分块懒加载
二、传统页面开发
在React、Vue这种数据驱动的框架还没盛行的时候,一般我们都是直接在html上写dom结构的,要不就是直接服务端直出,所以我们在下载完html页面后,空白屏的时间是非常短的,因为dom是在html中的,并不是像现在以虚拟dom的方式写在js中,所以,我们不需要等待js下载完毕后才开始渲染页面,而是html下载完毕后直接渲染出dom结构。
如今我们运用Vue等框架进行开发的时候,一般在html结构都是下面这样的
title
在js资源没有下载完毕的情况下,页面一直都是处于空白的页面,一直要等到虚拟dom插入到id为app的div中,这时候白屏才消失开始展现页面,反正就是让人感觉特别慢就是了!
既然知道了白屏是怎么产生的,那我们下面就来尝试一下如何在webpack中集成预渲染的功能,来降低白屏的时间。
三、在webpack中集成预渲染功能
github:webpack中如何集成预渲染功能
这里我们尝试将一个使用vue编写的loading组件在webpack编译过程中将虚拟dom预渲染到html中,下面是loading组件的内容
上面__inline__是用于后面图片插入的标记,这里先不用管,其实这个组件就是一个简单的loading组件
最终我们想要的效果是,将这个vue组件的虚拟dom预渲染到html文件当中
test ......
向上面那样,在html页面返回时编译成base64内嵌到html中的loading就会马上显示,大大降低了白屏的时间,基本可以达到秒开页面,这时候我们不需要等待js资源的下载以及虚拟dom的插入,当然这里loading中的内容可以是任何你想要预先渲染的模板
因为这里我们的loading组件是用vue写的,所以我们试着看看如何来做预渲染并集成到webpack中(可以合着仓库的代码一起看,代码挺简单的,只是一个demo)
这里我们先把vue单文件中的html与css单独抽离出来
// render-loading.js let vueAssets = null let vueTplPath = resolvePath('./src/loading/pre-render-loading.vue') const extractAssetsInVueTpl = (vueTplPath) => { let vueTpl = clearEnter(fs.readFileSync(vueTplPath).toString()) let html = /(.*)/g.exec(vueTpl)[1] let css = //g.exec(vueTpl)[1] return { html, css } } vueAssets = extractAssetsInVueTpl(vueTplPath)
这里我们通过正则的方式将template与style标签中匹配到的内容单独抽离了出来,接下来我们需要将gif图转成base64并插入到我们抽出的css代码当中
let gifPath = resolvePath('./src/loading/imgs/loading.gif') const transGifToCSSFile = (imgPath) => { let ext = path.extname(imgPath).slice(1) let preStr = `data:image/${ext};base64,` // 根据尾缀自动拼接对应base64前缀 let bitDate = fs.readFileSync(imgPath) let base64Str = bitDate.toString('base64') let dataURL = preStr + base64Str return dataURL } let dataURL = transGifToCSSFile(gifPath)
上面我们通过extractAssetsInVueTpl函数抽离出了css,这里我们通过一个简单的函数将占位符替换成base64图片
const injectDataURLToCSS = (cssStr, dataURL) => { return cssStr.replace(/__inline__/, dataURL) } let cssStr = injectDataURLToCSS(vueAssets.css, dataURL)
下面我们就导出loading配置,包含了html模板与style样式字符串
loading.html = vueAssets.html loading.css = '' module.exports = loading
简单写一个webpack入口配置,这里我们需要使用html-webpack-plugin将loading插入到html中(这里用到了插件的自定义模板)
const HtmlWebpackPlugin = require('html-webpack-plugin') const loading = require('./render-loading') module.exports = { entry: './src/index.js', output: { path: __dirname + '/dist', filename: 'index_bundle.js' }, plugins: [ new HtmlWebpackPlugin({ template: './src/index.html', loading: loading }) ] }
在html中我们通过模板语法将loading的内容插入到html模板中对应的位置了
test ... <%= htmlWebpackPlugin.options.loading.css %><%= htmlWebpackPlugin.options.loading.html %>...
四、总结
这里只是写一个demo介绍一下原理,更复杂的可以使用vue-server-render来做同构直出或者使用一些像handlebars的模板引擎来生成模板,其实就是将服务端的渲染工作放到了编译的过程当中。相关文章
- 人们熟悉的寄居蟹属于以下哪种分类 神奇海洋11月21日答案 11-21
- 第五人格11.22共研服有什么更新 11月22日共研服更新内容介绍 11-21
- 原神恰斯卡怎么培养 11-21
- 无期迷途四星装束是谁 11-21
- 王者荣耀帝丹高中校服怎么获得 11-21
- 光遇姆明季后续版本怎么玩 11-21