国外方案 组件化_网页webp解决方案
背景說明
某個(gè)國際化項(xiàng)目。前端用的技術(shù)棧是vue全家桶,使用nuxt-ssr渲染。
項(xiàng)目遇到的問題
項(xiàng)目中用到了大量的產(chǎn)品圖片和比較大的banner圖片。因?yàn)榉?wù)器在國外,也沒有對(duì)靜態(tài)服務(wù)器有相應(yīng)的配置cdn服務(wù),所以用戶在第一次訪問的時(shí)候,由于沒有緩存所以導(dǎo)致圖片渲染非常的慢,導(dǎo)致我們網(wǎng)站的體驗(yàn)非常大。
解決問題的想法
優(yōu)化千萬條,圖片第一條。加載特別慢,用戶兩行淚。好吧,我們這次要解決主要就是圖片加載慢的問題。有幾個(gè)客觀因素我們暫時(shí)無法避免
既然沒有辦法從硬件方便入手,那么只能從另外兩方面入手
優(yōu)雅的加載
我們?cè)趺床拍茉趫D片下載前,告訴用戶我們正在加載呢?
這些看起來都不錯(cuò),但是都有一個(gè)問題,用戶無法感知這個(gè)圖片的大致內(nèi)容,或者說這些東西都和原圖跳躍性太大。
所以我們選擇的是第四種方案:放一個(gè)體積在1kb左右特別模糊的小圖,然后放大展示。
webp
加載的問題解決了,那么有質(zhì)量又高,體積又小的圖片格式是什么,沒錯(cuò)是webp。
關(guān)于這個(gè)格式的來龍去脈網(wǎng)上有很多介紹,我就不搬磚了(詳情見下面兩個(gè)鏈接)
https://www.zhihu.com/question/27201061
https://aotu.io/notes/2016/06/23/explore-something-of-webp/index.html
根據(jù)這些資料,我們可以總結(jié)一下webp的特點(diǎn):
所以優(yōu)化圖片的格式就選擇了webp。
技術(shù)調(diào)研
有了上面的思考,我們的想法應(yīng)該是,不能慫,就是干。
我們來仔細(xì)的分析一下上面的這個(gè)需求,大致我拆分大兩點(diǎn)
圖片是怎么來的
我不想知道我是怎么沒的, 我就想知道我是怎么來的缺圖片?找設(shè)計(jì)。好吧,如果我們?nèi)フ以O(shè)計(jì)要這種圖片,設(shè)計(jì)拒絕了我們并且給了一段鄙視語。情理之中,畢竟重復(fù)工作誰都不愿意做。
那我們就讓機(jī)器去做。
具體的想法是,我們能不能在項(xiàng)目打包的時(shí)候,順便把需要的圖片都生成出來。那肯定可以,這樣的需求看起來有一個(gè)東西特別適合來做,webpack的plugin鉤子(為什么不用loader?)。簡單講就是,當(dāng)我們使用本項(xiàng)目的圖片的時(shí)候比如require('image/bg.jpg')的時(shí)候。webpack會(huì)觸發(fā)compiler.hooks的部分聲明周期,當(dāng)我們?cè)诖虬吧少Y源的時(shí)候,獲取到源圖片,然后進(jìn)行一系列的圖片轉(zhuǎn)換,再把轉(zhuǎn)換后的webp和min圖片掛載到打包的過程上。這樣圖片也就被我們?cè)斐鰜砹恕?/p>
功能是怎么被組件化的
要做就要做一個(gè)脫離業(yè)務(wù)的組件出來,也就是造個(gè)能跑的輪子。按照正常的邏輯可以先理解一下步驟
對(duì)于上面的總結(jié),我們列出個(gè)步驟
說明:上面的三張圖片我們采用了一個(gè)規(guī)定:
注:當(dāng)然要支持遠(yuǎn)程的圖片啦,所以還要提供一個(gè)修改webp圖和mini圖片路徑的入口,并且增加是否加載這兩種圖片的判斷。
Vue技術(shù)棧
好吧,不吐槽vue了,都挺好。我們的技術(shù)棧是vue,所以這次組件的設(shè)計(jì)也是基于vue了。
我們的想法應(yīng)該對(duì)組件有幾種用法
<LazyBackgroundclass="test":src = "require('./images/logo.jpg')" >測試地址11123 </LazyBackground>// 或者 <LazyBackgroundcssStyle={style.container}className={appStyle.box}src={require('./assets/bg.jpg')} >使用全部功能的組件 </LazyBackground> <LazyBackgroundcssStyle={style.container}className={[appStyle.box]}miniOptions={false}src={require('./assets/bg.jpg')} >不需要加載小圖的組 </LazyBackground> <LazyBackgroundcssStyle={style.container}webpOptions={false}src={require('./assets/bg.jpg')} >不需要加載webp的組件 </LazyBackground> <LazyBackgroundcssStyle={style.container}miniOptions={{src: src => src}}webpOptions={{src: src => src}}src={require('./assets/bg.jpg')} >分別設(shè)置小圖和webp圖片的路徑 </LazyBackground>對(duì)于上面的參數(shù)目前有幾個(gè)要求
{cssStyle //接受一個(gè)style對(duì)象,添加到外層的div上className // 接受一個(gè)字符串或者數(shù)組,添加到外層的div上src // 默認(rèn)圖片路徑miniOptions // 配置小圖路徑,默認(rèn)接受一個(gè)含有src的對(duì)象,src是一個(gè)函數(shù),接受處理過的url地址,默認(rèn)小圖的名稱是原圖后加 -minwebpOptions // 和上面一樣,默認(rèn)webp的圖片名稱是將后綴修改為 .webp } // (miniOptions和webpOptions)上面兩個(gè)參數(shù),如果不需要?jiǎng)t直接設(shè)置成false,這樣組件就不會(huì)加載對(duì)應(yīng)圖片,防止404出現(xiàn)Webpack打包方案
webpack是個(gè)極其優(yōu)秀的打包方案,其中l(wèi)oader可以讓這個(gè)平臺(tái)直接加載和優(yōu)化各種后綴的問題,而plugin更是讓海量的想法提供了落地的可能。(webpack如果不熟的一定要好好學(xué)一下)
我們相擁webpack做一個(gè)這樣的plugin
new webpackPluginImageTransformWebpAndMini({name: '[name]-[hash:8].[ext]',logger: true,webpOptions: {src: src => src.replace(/(?:.w+)(?|$)/, '.webp$1')},miniOptions: {src: src => src.replace(/.(w+?)(?[sS]+)?$/,'-min.$1$2'),resize: {width: 100}},paths: {dir: path.resolve(__dirname, './src/assets'),include: ['bg']} })其中有幾個(gè)參數(shù)要說明一下
- name 非必填項(xiàng),主要和圖片的file-loader或者url-loader采用的規(guī)則一樣默認(rèn)是'[name]-[hash:8].[ext]'(是因?yàn)関ue-cli生成出來的配置是這樣的) - paths 必填項(xiàng),會(huì)根據(jù)用戶所填的路徑進(jìn)行轉(zhuǎn)換(可遞歸)- 字符串:只是將此路徑下的圖片進(jìn)行轉(zhuǎn)換- 對(duì)象:{dir: 路徑include: 字符串?dāng)?shù)組,只是在該路徑下指定的文件進(jìn)行轉(zhuǎn)換exclude: 字符串?dāng)?shù)組,只是在該路徑下除去指定的文件進(jìn)行轉(zhuǎn)換} - logger 是否打印日志,默認(rèn)是false - webpOptions,對(duì)生成的webp的路徑進(jìn)行配置,接受一個(gè)函數(shù),參數(shù)是圖片名稱,需要返回一個(gè)字符串作為圖片的名稱。默認(rèn)只是將圖片的后綴修改為wepb{src: src => src} - miniOptions,對(duì)生成的小圖進(jìn)行配置,{src: src => src // 和上面的功能一樣,默認(rèn)把圖片的名稱后面加入-min后綴resize: { // 要壓縮的圖片大小,如果只寫一個(gè),那么默認(rèn)進(jìn)行比例,默認(rèn)width為100width: xxxheight: xxx}}工程化
有了上面的plugin,我們就可以根據(jù)原圖片生成對(duì)應(yīng)的小圖與webp格式圖片。有了這個(gè)組件,我們就可以直接使用生成后的圖片來完成想要的效果。
下面簡單實(shí)現(xiàn)一些上面的代碼
解決方案
根據(jù)上面的使用方案,我們簡單實(shí)現(xiàn)一些,為了提高一些逼格,下面的代碼都是用的ts和tsx來完成的。
組件化延遲背景圖方案
組件的都是使用tsx來寫的。詳細(xì)代碼就不介紹了,有興趣的可以看一下ropo。
插件化處理圖片生成
上面是簡單的目錄結(jié)構(gòu)
簡單介紹一下:
index.ts
插件入口問題,處理默認(rèn)的參數(shù),定義apply方法掛載相應(yīng)的鉤子
core.ts
插件核心方法:
utils.ts
提供工具方法:判斷類型
logger.ts
打印方法
interface.ts
項(xiàng)目中接口規(guī)則
各種配置
各種配置提供了ts的簡單配置和node端打包的簡單配置。
示例
簡單的看下圖片對(duì)比加載過程
vue-dome
頭部的簡單的效果,貼一下代碼
上面就是一個(gè)簡單的目錄,圖片就是個(gè)背景
vue.config.js
const webpackPluginImageTransformWebpAndMini = require('webpack-plugin-image-transform-webp-and-mini') const path = require('path') module.exports = {configureWebpack: {plugins: [new webpackPluginImageTransformWebpAndMini({paths: {dir: path.resolve(__dirname, './src/assets'),include: ['bg']}})]} }main.js
import Vue from 'vue' import App from './App.vue' import LazyBackground from 'vue-lazy-background-component' Vue.use(LazyBackground)Vue.config.productionTip = falsenew Vue({render: h => h(App), }).$mount('#app')App.vue
<template><div id="app"><LazyBackgroundclass="test":src = "require('./assets/bg.jpg')">測試地址11123</LazyBackground><img class="test" alt="Vue logo" src="./assets/bg.jpg"></div> </template><script> export default {name: 'app' } </script><style> #app {font-family: 'Avenir', Helvetica, Arial, sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;color: #2c3e50;margin-top: 60px; } .test {width: 540px;height: 300px;background-size: cover; } </style>運(yùn)行npm run serve,即可看到頭圖效果。
運(yùn)行npm run build,可以看到圖片都已經(jīng)自動(dòng)生成出來
npm
兩個(gè)包目前都已經(jīng)推倒了npm上了,需要的可以上去試試,可以直接用vue-cli生成的項(xiàng)目進(jìn)行試驗(yàn)
https://www.npmjs.com/package/webpack-plugin-image-transform-webp-and-mini
https://www.npmjs.com/package/vue-lazy-background-component
github
如果想看源碼的可以在github上,源碼都是用ts寫的,因此無論是配置還是代碼,都是建議看一看
https://github.com/wuyxp/webpack-plugin-image-transform-webp-and-mini
https://github.com/wuyxp/vue-lazy-background-component
總結(jié)
寫了這兩個(gè)東西,學(xué)到了很多東西,尤其是webpack。深刻的認(rèn)識(shí)到了,webpack是個(gè)后置技能,我們只是在配置文件上簡單的配置幾項(xiàng)內(nèi)容而webpack在背后要做很多大量的工作去完成。所以要想學(xué)好前端工程,webpack及webpack背后的思想是一定要學(xué)習(xí)的。
還有一件事:996.icu很無聊。
總結(jié)
以上是生活随笔為你收集整理的国外方案 组件化_网页webp解决方案的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 车上epc是什么意思?
- 下一篇: 宝马4s店的维修保养记录里qty是什么意