共计 1693 个字符,预计需要花费 5 分钟才能阅读完成。
又名给 vuepress 写一个插件😊
最终的成果如下
思路
最近在看 pwa 时,在 MDN 上看见一段乏味的对于实现渐进式图片加载的 snippet,粗心如下:
<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,而后再去加载真正的原图,当原图加载结束后,再渲染原图。这缩短了页面加载渲染的工夫,让用户关上页面可能疾速取得反馈。
咱们可能在 medium 和 gatsby.js 网站上见到过这种图片加载形式,然而 vuepress 自身是不反对的,于是便想实现这种图片加载形式,顺便写一个 vuepress 插件。
实现的步骤如下:
1. 生成一张缩略图,而后插入进去
依据需要,咱们想要这样一个 markdown 解析成果
![image](./origin.jpg)
解析后为:
<img src="./thumbnial.jpg" data-src="./orign.jpg"></img>
首先须要阐明一下一个 vuepress 页面是如何生成的
markdown-loader vue-loader
markdown--------------->vue SFCs?------>vue spa
上述并不精确,因为没有去深究两头产物到底是什么。
回到主线上,官网上给出,vuepress 应用 markdonw-it
作为 markdown 的解析器,即上述的 markdown-loader 其实就是一个包装后的 markdown-it
,同时 vuepress 暴露出了extendMarkdown
这一 api 用来改写 markdown 解析规定。
所以,咱们能够通过这一 api,插入咱们自定义的对于图片的解析规定就可能实现咱们所须要的后果。于是咱们能够写一个 mark-it 的插件来实现这一性能。
在这,我遇到了两个坑,别离是
- markdown-it 插件仅反对同步函数
- vue-loader 默认不解析
data-src
这一 attribute. 因为 vuepres 应用了url-loader
,所以会将图片之类的动态文件给寄存在assets/images
文件夹下,而data-src
中的图片地址却不会发生变化。
第二个十分好办,咱们能够通过 chainWebpack
这一 api 该变 vuepress 的 webpack config 就能够实现,即在 vueloader 的 transformAssetUrls
上增加 img:["data-src"]
就好了。
对于第一个生成原图片的缩略图,我应用了 imageThumbnail
库,该库仅反对异步办法。所以咱们须要将该异步办法包装成真正的同步办法。这里应用到了一个 deasync
的库,它裸露了 node 底层的一个 sleep()
办法,来使 main line 强制挂起,提前进行事件循环,直到事件循环完结,再执行主线程序来实现同步。
2. 加载原图片
这一步能够应用 clientRootMixin
这一 api,给 globalLayout.vue
混入一个全局的办法就能够了~
具体代码能够看一下俺的 github 仓库,因为接触 vuepress 不深刻,有些局部的实现十分的 naive,而且整个代码也不是很优雅,很多办法都十分生硬,欢送大家 pr 或者本人编写代码更好地实现👏。
另,我将该插件上传到了 npm 上,大家能够 npm install 玩一玩~
$ npm install vuepress-plugin-progressive-image-loader