又名給vuepress寫一個插件😊
最終的效果以下css
最近在看pwa時,在MDN上看見一段有趣的關於實現漸進式圖片加載的snippet,大意以下:html
<img src="thumbnail.png" data-src="origin.png"></img>
var imgToLoad=document.qureySelectorAll('img[data-src]') imgToLoad.forEach(img=>{ img.setAttribute('src',imgAttribute('data-src')); img.onload=()=>{ img.removeAttribute('data-src') } })
img[data-src] { filter: blur(0.2em); } img { filter: blur(0em); transition: filter 0.3s; }
總得來講即是在加載渲染頁面時,先加載和渲染頁面的縮略圖,做爲一個placeholder,而後再去加載真正的原圖,當原圖加載完畢後,再渲染原圖。這縮短了頁面加載渲染的時間,讓用戶打開頁面可以快速得到反饋。vue
咱們可能在medium和gatsby.js網站上見到過這種圖片加載方式,可是vuepress自己是不支持的,因而便想實現這種圖片加載方式,順便寫一個vuepress插件。node
實現的步驟以下:webpack
根據需求,咱們想要這樣一個markdown解析效果git

解析後爲:github
<img src="./thumbnial.jpg" data-src="./orign.jpg"></img>
首先須要說明一下一個vuepress頁面是如何生成的web
markdown-loader vue-loader markdown--------------->vue SFCs?------>vue spa
上述並不許確,由於沒有去深究中間產物究竟是什麼。
回到主線上,官網上給出,vuepress使用markdonw-it
做爲markdown的解析器,即上述的markdown-loader其實就是一個包裝後的markdown-it
,同時vuepress暴露出了extendMarkdown
這一api用來改寫markdown解析規則。
因此,咱們能夠經過這一api,插入咱們自定義的關於圖片的解析規則就可以實現咱們所須要的結果。因而咱們能夠寫一個mark-it的插件來實現這一功能。
在這,我遇到了兩個坑,分別是shell
data-src
這一attribute.由於vuepres使用了url-loader
,因此會將圖片之類的靜態文件給存放在assets/images
文件夾下,而data-src
中的圖片地址卻不會發生變化。第二個很是好辦,咱們能夠經過chainWebpack
這一api該變vuepress的webpack config就能夠實現,即在vueloader的transformAssetUrls
上添加img:["data-src"]
就行了。npm
對於第一個生成原圖片的縮略圖,我使用了imageThumbnail
庫,該庫僅支持異步方法。因此咱們須要將該異步方法包裝成真正的同步方法。這裏使用到了一個deasync
的庫,它暴露了node底層的一個sleep()
方法,來使main line 強制掛起,提早進行事件循環,直到事件循環結束,再執行主線程序來實現同步。
這一步可使用clientRootMixin
這一api,給globalLayout.vue
混入一個全局的方法就能夠了~
具體代碼能夠看一下俺的github倉庫,因爲接觸vuepress不深刻,有些部分的實現很是的naive,並且整個代碼也不是很優雅,不少方法都很是僵硬,歡迎你們pr或者本身編寫代碼更好地實現👏。
另,我將該插件上傳到了npm上,你們能夠npm install玩一玩~
$ npm install vuepress-plugin-progressive-image-loader