国外方案 组件化_网页webp解决方案
背景說明
某個國際化項目。前端用的技術棧是vue全家桶,使用nuxt-ssr渲染。
項目遇到的問題
項目中用到了大量的產品圖片和比較大的banner圖片。因為服務器在國外,也沒有對靜態服務器有相應的配置cdn服務,所以用戶在第一次訪問的時候,由于沒有緩存所以導致圖片渲染非常的慢,導致我們網站的體驗非常大。
解決問題的想法
優化千萬條,圖片第一條。加載特別慢,用戶兩行淚。好吧,我們這次要解決主要就是圖片加載慢的問題。有幾個客觀因素我們暫時無法避免
既然沒有辦法從硬件方便入手,那么只能從另外兩方面入手
優雅的加載
我們怎么才能在圖片下載前,告訴用戶我們正在加載呢?
這些看起來都不錯,但是都有一個問題,用戶無法感知這個圖片的大致內容,或者說這些東西都和原圖跳躍性太大。
所以我們選擇的是第四種方案:放一個體積在1kb左右特別模糊的小圖,然后放大展示。
webp
加載的問題解決了,那么有質量又高,體積又小的圖片格式是什么,沒錯是webp。
關于這個格式的來龍去脈網上有很多介紹,我就不搬磚了(詳情見下面兩個鏈接)
https://www.zhihu.com/question/27201061
https://aotu.io/notes/2016/06/23/explore-something-of-webp/index.html
根據這些資料,我們可以總結一下webp的特點:
所以優化圖片的格式就選擇了webp。
技術調研
有了上面的思考,我們的想法應該是,不能慫,就是干。
我們來仔細的分析一下上面的這個需求,大致我拆分大兩點
圖片是怎么來的
我不想知道我是怎么沒的, 我就想知道我是怎么來的缺圖片?找設計。好吧,如果我們去找設計要這種圖片,設計拒絕了我們并且給了一段鄙視語。情理之中,畢竟重復工作誰都不愿意做。
那我們就讓機器去做。
具體的想法是,我們能不能在項目打包的時候,順便把需要的圖片都生成出來。那肯定可以,這樣的需求看起來有一個東西特別適合來做,webpack的plugin鉤子(為什么不用loader?)。簡單講就是,當我們使用本項目的圖片的時候比如require('image/bg.jpg')的時候。webpack會觸發compiler.hooks的部分聲明周期,當我們在打包前生成資源的時候,獲取到源圖片,然后進行一系列的圖片轉換,再把轉換后的webp和min圖片掛載到打包的過程上。這樣圖片也就被我們造出來了。
功能是怎么被組件化的
要做就要做一個脫離業務的組件出來,也就是造個能跑的輪子。按照正常的邏輯可以先理解一下步驟
對于上面的總結,我們列出個步驟
說明:上面的三張圖片我們采用了一個規定:
注:當然要支持遠程的圖片啦,所以還要提供一個修改webp圖和mini圖片路徑的入口,并且增加是否加載這兩種圖片的判斷。
Vue技術棧
好吧,不吐槽vue了,都挺好。我們的技術棧是vue,所以這次組件的設計也是基于vue了。
我們的想法應該對組件有幾種用法
<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')} >分別設置小圖和webp圖片的路徑 </LazyBackground>對于上面的參數目前有幾個要求
{cssStyle //接受一個style對象,添加到外層的div上className // 接受一個字符串或者數組,添加到外層的div上src // 默認圖片路徑miniOptions // 配置小圖路徑,默認接受一個含有src的對象,src是一個函數,接受處理過的url地址,默認小圖的名稱是原圖后加 -minwebpOptions // 和上面一樣,默認webp的圖片名稱是將后綴修改為 .webp } // (miniOptions和webpOptions)上面兩個參數,如果不需要則直接設置成false,這樣組件就不會加載對應圖片,防止404出現Webpack打包方案
webpack是個極其優秀的打包方案,其中loader可以讓這個平臺直接加載和優化各種后綴的問題,而plugin更是讓海量的想法提供了落地的可能。(webpack如果不熟的一定要好好學一下)
我們相擁webpack做一個這樣的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']} })其中有幾個參數要說明一下
- name 非必填項,主要和圖片的file-loader或者url-loader采用的規則一樣默認是'[name]-[hash:8].[ext]'(是因為vue-cli生成出來的配置是這樣的) - paths 必填項,會根據用戶所填的路徑進行轉換(可遞歸)- 字符串:只是將此路徑下的圖片進行轉換- 對象:{dir: 路徑include: 字符串數組,只是在該路徑下指定的文件進行轉換exclude: 字符串數組,只是在該路徑下除去指定的文件進行轉換} - logger 是否打印日志,默認是false - webpOptions,對生成的webp的路徑進行配置,接受一個函數,參數是圖片名稱,需要返回一個字符串作為圖片的名稱。默認只是將圖片的后綴修改為wepb{src: src => src} - miniOptions,對生成的小圖進行配置,{src: src => src // 和上面的功能一樣,默認把圖片的名稱后面加入-min后綴resize: { // 要壓縮的圖片大小,如果只寫一個,那么默認進行比例,默認width為100width: xxxheight: xxx}}工程化
有了上面的plugin,我們就可以根據原圖片生成對應的小圖與webp格式圖片。有了這個組件,我們就可以直接使用生成后的圖片來完成想要的效果。
下面簡單實現一些上面的代碼
解決方案
根據上面的使用方案,我們簡單實現一些,為了提高一些逼格,下面的代碼都是用的ts和tsx來完成的。
組件化延遲背景圖方案
組件的都是使用tsx來寫的。詳細代碼就不介紹了,有興趣的可以看一下ropo。
插件化處理圖片生成
上面是簡單的目錄結構
簡單介紹一下:
index.ts
插件入口問題,處理默認的參數,定義apply方法掛載相應的鉤子
core.ts
插件核心方法:
utils.ts
提供工具方法:判斷類型
logger.ts
打印方法
interface.ts
項目中接口規則
各種配置
各種配置提供了ts的簡單配置和node端打包的簡單配置。
示例
簡單的看下圖片對比加載過程
vue-dome
頭部的簡單的效果,貼一下代碼
上面就是一個簡單的目錄,圖片就是個背景
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>運行npm run serve,即可看到頭圖效果。
運行npm run build,可以看到圖片都已經自動生成出來
npm
兩個包目前都已經推倒了npm上了,需要的可以上去試試,可以直接用vue-cli生成的項目進行試驗
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
總結
寫了這兩個東西,學到了很多東西,尤其是webpack。深刻的認識到了,webpack是個后置技能,我們只是在配置文件上簡單的配置幾項內容而webpack在背后要做很多大量的工作去完成。所以要想學好前端工程,webpack及webpack背后的思想是一定要學習的。
還有一件事:996.icu很無聊。
總結
以上是生活随笔為你收集整理的国外方案 组件化_网页webp解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 车上epc是什么意思?
- 下一篇: 中绘制折线_啥是折线图?啥时候用?怎么用