您好,登錄后才能下訂單哦!
小編給大家分享一下在webpack中做預渲染降低首屏空白時間的案例,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
一、瀏覽器渲染過程
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結構都是下面這樣的
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>title</title> </head> <body> <div id="app"></div> <script src="/bound.js"></script> </body> </html>
在js資源沒有下載完畢的情況下,頁面一直都是處于空白的頁面,一直要等到虛擬dom插入到id為app的div中,這時候白屏才消失開始展現頁面,反正就是讓人感覺特別慢就是了!
既然知道了白屏是怎么產生的,那我們下面就來嘗試一下如何在webpack中集成預渲染的功能,來降低白屏的時間。
三、在webpack中集成預渲染功能
github:webpack中如何集成預渲染功能
這里我們嘗試將一個使用vue編寫的loading組件在webpack編譯過程中將虛擬dom預渲染到html中,下面是loading組件的內容
<template> <div class="loading-img"></div> </template> <script> export default {} </script> <style> .loading-img { position: fixed; top: 0; bottom: 0; right: 0; left: 0; margin: auto; display: inline-block; width: 60px; height: 60px; background: url(__inline__) no-repeat center center; background-size: contain; } </style>
上面__inline__是用于后面圖片插入的標記,這里先不用管,其實這個組件就是一個簡單的loading組件
最終我們想要的效果是,將這個vue組件的虛擬dom預渲染到html文件當中
<html> <head> <meta charset="UTF-8"> <title>test</title> <!-- pre-render-loading抽出的css --> <style> .loading-img { position: fixed; top: 0; bottom: 0; right: 0; left: 0; margin: auto; display: inline-block; width: 60px; height: 60px; <!-- 這里我們會將loading圖編譯成base64直接插入到html中 --> background: url(data:image/gif;base64,.....) no-repeat center center; background-size: contain; } </style> ... </head> <body> <div id="app"> <!-- loading base64圖 --> <div class="loading-img"></div> </div> ... </body> </html>
向上面那樣,在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 = /<template>(.*)<\/template>/g.exec(vueTpl)[1] let css = /<style>(.*)<\/style>/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 = '<style>' + cssStr + '</style>' 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模板中對應的位置了
<html> <head> <meta charset="UTF-8"> <title>test</title> ... <%= htmlWebpackPlugin.options.loading.css %> </head> <body> <div id="app"> <!-- loading base64圖 --> <%= htmlWebpackPlugin.options.loading.html %> </div> ... </body> </html>
看完了這篇文章,相信你對“在webpack中做預渲染降低首屏空白時間的案例”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。