無心中看到了這篇關於使用LQIP(Low Quality Image Placeholders) 原文連接,方案實現圖片加載優化方案。在此實踐一把。javascript
1. 方案實現html
監聽頁面是否滾動到圖片位置使用的IntersectionObserver,減小使用scroll過程形成的頁面卡頓。java
2. 代碼結構node
index.tmplgit
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>lasyload and LQIP</title> <meta name="viewport" id="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no"> <link rel="shortcut icon" href="/favicon.ico"> <meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-status-bar-style" content="black"> <meta name="format-detection" content="telephone=no"> </head> <body> <p>You may need to install go and Primitive</p> <p> This is long article. <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <img src="./images/1.jpg" class="big-pic" alt=""> <br/><br/><br/> next line <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> <img src="./images/2.jpg" class="big-pic" alt=""> <br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><br/> 3th picture <br/> <br/> <img src="./images/3.jpg" class="big-pic" alt=""> </p> <script type='text/javascript' src='./bundle.js'></script> </body> </html>
lib/index.jsgithub
function replaceSrc (changes) { changes.forEach(change => { if (change.intersectionRatio <= 0) return let item = change.target let src = item.getAttribute('data-src') let img = new Image() img.onload = function () { item.setAttribute('src', src) } img.src = src // observer.unobserve(item) }) } module.exports = function (selector) { let els = document.querySelectorAll(selector) let observer = new IntersectionObserver(replaceSrc.bind()); [].forEach.call(els, (item) => { observer.observe(item) }) }
index.jsgolang
let dealPic = require('../lib/index')
dealPic('.big-pic')
各文件關係是:web
3. 構建的實現npm
首先須要安裝go和primitive. primitive庫: https://github.com/fogleman/primitive服務器
安裝primitive時有些網站被牆了,因此要下載安裝包安裝。網上搜索到了一個第三方下載地址:https://www.golangtc.com/download/package
按提示下載解壓至go目錄下的src,而後執行
go install github.com/fogleman/primitive
安裝完成環境。
安裝npm庫依賴包:
npm i glob sqip browserify
使用glob檢索全部的圖片,sqip用於轉換圖片爲最小格式的svg,browserify爲了使用require模塊。
使用正則檢測出html模板中全部的img, 匹配已經轉爲svg的文件,文件相同,使用base64格式替換掉原src,新加data-src爲原src, 設置width height等。最後輸出文件爲index.html
構建的代碼以下:
const sqip = require('sqip') const glob = require('glob') const path = require('path') const fs = require('fs') function getSvgList (folder) { return new Promise((resolve, reject) => { glob(folder + '/**/*.jpg', {}, function (err, files) { if (err) { reject(err) } let list = [] files.forEach(file => { const result = sqip({ filename: file, numberOfPrimitives: 10, }) list.push({ file: path.join(__dirname, file), result, }) }) resolve(list) }) }) } function replaceHtml (html, list) { if (!path.isAbsolute(html)) { html = path.join(__dirname, html) } let str = fs.readFileSync(html, 'utf-8') let htmlPath = path.dirname(html) const REG = /(<img .*?src=\")(.*?)\"( .*?>)/g let imgSrc = REG.exec(str) while (imgSrc) { let src = imgSrc[2] let file if (path.isAbsolute(src)) { file = path.join(__dirname, src) } else { file = path.join(htmlPath, src) } list.forEach(item => { if (item.file === file) { var imgInfo = item.result.img_dimensions str = str.replace(imgSrc[0], function (str) { return imgSrc[1] + 'data:image/svg+xml;base64,' + item.result.svg_base64encoded + `" data-width="${imgInfo.width}" data-height="${imgInfo.height}"` + ` data-src="${src}"` + imgSrc[3] }) } }) imgSrc = REG.exec(str) } fs.writeFileSync('./example/index.html', str) } getSvgList('./example/images/') .then(list => { replaceHtml('./example/index.tmpl', list) })
4. 執行構建並檢測結果
在npm中加入scripts:
{ "build": "npm run sqip & browserify example/index.js -o example/bundle.js", "sqip": "node sqip.js" }
執行build後,example文件目錄下會生成index.html。開啓web服務器(我是使用的本身寫的xmocker),訪問example/index.html,使用throttle進行查看效果。
5. 總結
方案只是針對普通Html,對於其餘模塊,應該有現成的方案。訪問體驗確實好了不少。
附:代碼地址 https://github.com/wenlonghuo/code-test/tree/master/001_lasyload