在之前的系列文章中,我已經(jīng)介紹了如何用webpack實(shí)現(xiàn)多頁面應(yīng)用
的js牙丽,html,css的處理兔魂。今天就主要介紹如何處理靜態(tài)資源烤芦,在web開發(fā)中最常見的靜態(tài)資源就是圖片。
圖片的引用方式
而因?yàn)樵趙eb中析校,圖片有兩種主要的引入方式构罗,第一種是<img src="...">
铜涉,第二種是backgorund-image: url(...)
。前者在html中使用绰播,后者在css中使用骄噪。
web開發(fā)中的圖片處理
圖片常見的類型有jp(e)g,png蠢箩,gif链蕊,包括現(xiàn)在普遍使用的svg以及webp。svg作為矢量圖形谬泌,有一定的使用場(chǎng)景滔韵,而webp作為未來web開發(fā)的趨勢(shì),有一定的使用場(chǎng)景掌实,比如:愛奇藝中的輪播圖(carousel)中就是用webp陪蜻,但其他的見到的不多。
現(xiàn)在贱鼻,web開發(fā)中使用最多的還是jpg和png宴卖,處理他們,在構(gòu)建工具中使用url-loader
和file-loader
就好了邻悬,其中file-loader負(fù)責(zé)圖片的拷貝和輸出症昏,并會(huì)給圖片名添加一個(gè)hash值。
說到這里父丰,很多人會(huì)想到字體圖標(biāo)
肝谭。以前處理web頁面中的圖標(biāo)(icon),使用圖片來處理蛾扇,這樣會(huì)帶來一個(gè)性能問題就是http請(qǐng)求的增多攘烛,這樣會(huì)造成服務(wù)器的負(fù)載壓力,同時(shí)會(huì)帶來用戶體驗(yàn)的問題镀首,因?yàn)闀?huì)出現(xiàn)頁面的局部空白和頁面重繪的問題坟漱,當(dāng)然一種解決方案使雪碧圖(sprite),但是如果圖片過大怎么解決更哄,如何對(duì)圖片進(jìn)行分解(大變小的問題)靖秩,圖片的拼接比較困難,最要命的是在引用雪碧圖時(shí)要進(jìn)行計(jì)算竖瘾,除此之外就是如何對(duì)雪碧圖的組成圖片進(jìn)行自定義的刪減沟突,而使用字體圖標(biāo)這些問題,都會(huì)得到一定程度的解決捕传,當(dāng)然在構(gòu)建工具中可以使用webpack-spritesmith
這個(gè)插件來處理組成雪碧圖的圖片惠拭。
當(dāng)然,有些特殊的情況,需要使用base64
职辅,這里使用url-loader
即可棒呛。
將圖片處理為base64有使用場(chǎng)景,將圖片轉(zhuǎn)換為雪碧圖亦有使用場(chǎng)景域携,單獨(dú)的圖片處理也有使用場(chǎng)景(這些使用場(chǎng)景的圖片大小從左到右依次增大)簇秒。
這些場(chǎng)景在一個(gè)web項(xiàng)目中都會(huì)涉及到。
雖然使用字體圖標(biāo)可以替代雪碧圖秀鞭,因?yàn)樽煮w圖標(biāo)有更小的尺寸趋观,更自由的操作手法(如:圖標(biāo)顏色的自定義),但是一個(gè)DIY的web項(xiàng)目還是有些圖標(biāo)還是需要雪碧圖锋边。
但是皱坛,這里有一個(gè)問題,如何在一個(gè)項(xiàng)目中同時(shí)使用base64豆巨,雪碧圖剩辟,字體圖標(biāo),單獨(dú)的圖片往扔。
在構(gòu)建中如何使用多種圖片處理方式
在構(gòu)建多頁面應(yīng)用中贩猎,如何解決呢?
字體圖標(biāo)
處理字體圖標(biāo)很簡(jiǎn)單萍膛,如:iconfont(阿里巴巴字體圖標(biāo)庫)吭服,就像引用css那么簡(jiǎn)單。
base64
base64的處理卦羡,使用url-loader
噪馏。
雪碧圖
雪碧圖的處理麦到,可使用webpack-spritesmith
這個(gè)插件
單獨(dú)的圖片
使用file-loader
绿饵,它負(fù)責(zé)拷貝url-loader
的處理結(jié)果,并輸出瓶颠。
上面就是我們常見的圖片處理拟赊,如果要處理svg可以參考svg-url-loader
,如果要處理webp可以參考webp-loader
如何對(duì)圖片進(jìn)行優(yōu)化
對(duì)圖片進(jìn)行優(yōu)化粹淋,會(huì)帶來良好的用戶體驗(yàn)吸祟。
熟悉圖片優(yōu)化的都知道漸進(jìn)式(progressive),可參考nuwen.net
jp(e)g可以進(jìn)行連續(xù)性
處理桃移,這樣可保證圖片數(shù)據(jù)請(qǐng)求回來多少屋匕,就渲染多少,是自上而下的渲染借杰,也是有模糊到清晰的狀態(tài)过吻。
png可以進(jìn)行交叉
處理,這樣也可保證圖片數(shù)據(jù)請(qǐng)求回來多少,就渲染多少纤虽,它是整體的顯示乳绕,而且是又模糊狀態(tài)到清晰的狀態(tài)。
gif圖片一般使用小圖逼纸,如果是大圖會(huì)記號(hào)瀏覽器性能洋措,還不如使用視頻,或者用css動(dòng)畫來代替杰刽。我個(gè)人整理了一個(gè)css 動(dòng)畫集菠发,有需要的可以看一下。
在構(gòu)建多頁面應(yīng)用中专缠,會(huì)使用到image-webpack-loader
來做優(yōu)化處理雷酪。
其中,配置項(xiàng)options
中的mozjpeg
處理jp(e)g圖片涝婉,pngquant
處理png圖片哥力,gifsicle
處理gif圖片,webp
處理webp圖片墩弯。
多頁面應(yīng)用中的圖片處理
首先吩跋,看一下多頁面應(yīng)用中的目錄結(jié)構(gòu)圖:
./src
│ aboutUs.js
│ contactUs.js
│ css.js
│ index.js
│ recruitment.js
│
├─assets
│ │ favicon.jpg
│ │
│ ├─css
│ │ │ index.scss
│ │ │
│ │ ├─commons
│ │ │ ├─container
│ │ │ │ index.scss
│ │ │ │
│ │ │ ├─footer
│ │ │ │ index.scss
│ │ │ │
│ │ │ └─header
│ │ │ index.scss
│ │ │
│ │ ├─productus
│ │ │ index.scss
│ │ │ productus-sprite.scss
│ │ │
│ │ └─utils
│ │ btn.scss
│ │ form.scss
│ │ inital.scss
│ │ list.scss
│ │ modeal.scss
│ │ normalize.scss
│ │ pagination.scss
│ │ popover.scss
│ │ table.scss
│ │ text.scss
│ │ tooltip.scss
│ │
│ └─imgs
│ ├─base64
│ │ fe.jpg
│ │
│ ├─other
│ │ float.jpg
│ │ productus-sprite.png
│ │
│ └─sprites
│ └─productus
│ product-us_01.png
│ product-us_02.png
│ product-us_03.png
│ product-us_04.png
│ product-us_05.png
│ product-us_06.png
│ product-us_07.png
│ product-us_08.png
│ product-us_09.png
│ product-us_10.png
│ product-us_11.png
│ product-us_12.png
│
├─pages
│ │ recruitment.pug
│ │ template.pug
│ │
│ └─components
│ ├─commons
│ │ ├─container
│ │ │ index.pug
│ │ │
│ │ ├─footer
│ │ │ index.pug
│ │ │
│ │ └─header
│ │ index.pug
│ │
│ └─productus
│ index.pug
│
└─utils
load.js
跟以前的實(shí)例代碼相比,這次的文件目錄結(jié)構(gòu)變化較大渔工,這里將要處理的所有文件模塊都放在了src
目錄下锌钮。
可能有人會(huì)問,為什么要要將目錄分的這么細(xì)引矩,下面我就說一下為什么這么分梁丘。
-
aboutUs.js
,contactUs.js
,index.js
,recruitment.js
是四個(gè)路由頁面,要用到的js代碼旺韭,css.js
處理各個(gè)路由頁面公用的css代碼氛谜; - 靜態(tài)資源目錄(assets)下,存放web項(xiàng)目常用的靜態(tài)資源区端;
- 靜態(tài)資源目錄下的css目錄統(tǒng)一存放整個(gè)web項(xiàng)目所用到的css樣式值漫。其中commons存放公用的css模塊,每個(gè)公用模塊有創(chuàng)建一個(gè)目錄存放該公用模塊可以使用到的css模塊(提醒织盼,不要分的過于細(xì))杨何,而其他的如
productus
存放產(chǎn)品模塊代碼,根據(jù)開發(fā)的需要可以創(chuàng)建其他的模塊目錄沥邻,目錄結(jié)構(gòu)類似于commons
中的header
模塊危虱,其中utils
放置自己總結(jié)的工具模塊代碼,如table
唐全,form
等埃跷。然后,指定style-loader
,css-loader
等樣式相關(guān)的loader處理css樣式文件,這樣可以減少遍歷捌蚊,縮短構(gòu)建時(shí)間集畅。 - 靜態(tài)資源目錄下的imgs目錄,用來存放整個(gè)項(xiàng)目中缅糟,用到的圖片挺智。在這里,分為
base64
窗宦,sprite
赦颇,ohter
等,為什么要這樣分赴涵?如果分的話file-loader
這個(gè)webapck的loader會(huì)復(fù)制并導(dǎo)出imgs
目下所有的圖片媒怯,者在構(gòu)建中并不是我們需要的,這樣會(huì)增加構(gòu)建的時(shí)間髓窜。如果讓url-loader
處理base64
目錄下的圖片扇苞,file-loader
處理ohter
目錄下的圖片,webpack-spritesmith
處理sprite
目錄下的圖片寄纵,并將生成的圖片放到ohter
目錄下鳖敷,用file-loader
進(jìn)行二次處理。這樣做程拭,webpack處理更精確定踱,可以減少不必要的遍歷,極大地減少構(gòu)建的時(shí)間恃鞋,同樣方便對(duì)圖片的管理崖媚,特別是對(duì)于需要改變sprite
的圖片的管理。 - 在
imgs
目錄下創(chuàng)建base64
目錄恤浪,sprite
目錄畅哑,使用file-loader
指定處理ohter
目錄,是為了避免file-loader將所有的圖片都拷貝一份并導(dǎo)出到dist
輸出目錄中资锰,因?yàn)榕cbase64
相關(guān)的文件已經(jīng)在css
樣式文件中了敢课,再拷貝一份阶祭,已經(jīng)沒有意義绷杜,而sprite
相關(guān)的文件會(huì)被webpack-spritesmith
插件先處理生成一個(gè)文件,所以再拷貝它們也沒有意義濒募,還會(huì)讓構(gòu)建速度更慢鞭盟。 - 在
page
目錄下,放置所有的html代碼塊(這里使用pug編譯器生成相應(yīng)的html代碼塊)瑰剃,它的目錄分類和css
相類似齿诉,它們是一一對(duì)應(yīng)的關(guān)系。
注意:iamge-webpack-loader
,要先對(duì)所有的圖片進(jìn)行優(yōu)化處理粤剧,然后再用其他loader處理歇竟。loader的執(zhí)行順序,如果你是style-loader!css-loader!sass-loader"
使用抵恋,它是從右到左方向先后執(zhí)行焕议,如果你是在配置文件中的rules: [...]
數(shù)組中,它也是從右到左的方向執(zhí)行弧关,如果你將所有的loader規(guī)則有回車符號(hào)隔開盅安,那么它就是自下而上的執(zhí)行。
一類特殊的圖片引用
針對(duì)<img src="...">
的圖片使用世囊,ul-loader
是不會(huì)處理html中的img引用别瞭,現(xiàn)在處理這樣情況的loader或插件,也并沒有一個(gè)比較出名的≈旰叮現(xiàn)在通用的做法就是將圖片拷貝一份到生成目錄中蝙寨,copy-webpack-plugin
。參考配置代碼如下:
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, 'assets/imgs/other/'),
to: path.resolve(__dirname, 'dist/assets/imgs/other/'),
ignore: ['.*']
}
]),
但這樣嗤瞎,會(huì)帶來另一個(gè)問題就是圖片的優(yōu)化問題籽慢,如何使用 image-webpack-loader
?本來的目的是對(duì)項(xiàng)目中使用到的所有的圖片進(jìn)行優(yōu)化猫胁,而現(xiàn)在只能對(duì)base64
和sprite
目錄下的圖片進(jìn)行優(yōu)化處理箱亿。不過,不要慌弃秆,可以通過創(chuàng)建一個(gè)新的npm腳本命令(本是里使用的是npm run img
)來對(duì)圖片進(jìn)行壓縮處理届惋,新建了一個(gè)目錄static
用來保存優(yōu)化前的圖片,ohter
用來保存優(yōu)化后的圖片菠赚。
首先脑豹,需要安裝imagemin
, imagemin-mozjpeg
, imagemin-optipng
, imagemin-gifsicle
:
yarn add imagemin imagemin-mozjpeg imagemin-optipng imagemin-gifsicle --dev
然后,在項(xiàng)目的根目錄添加一個(gè)優(yōu)化圖片的文件optzing-img.js
衡查,代碼如下:
const path = require('path')
const imagemin = require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
const imageminOptipng = require('imagemin-optipng');
const imageminGifsicle = require('imagemin-gifsicle');
(async () => {
await imagemin(
[
path.resolve(__dirname, 'src/assets/imgs/static/*.jpg'),
path.resolve(__dirname, 'src/assets/imgs/static/*.png'),
path.resolve(__dirname, 'src/assets/imgs/static/*.gif')
],
path.resolve(__dirname, 'src/assets/imgs/other/'),
{
use: [
imageminMozjpeg(),
imageminOptipng(),
imageminGifsicle()
]
}
);
console.log('圖片優(yōu)化完成瘩欺!');
})();
最后,在package.json
文件中添加如下的npm命令:
...
"scripts": {
...
"img": "node optzing-img.js"
},
...
在控制輸入npm run img
拌牲,然后按下回車鍵就可以得到你所需要的俱饿。
注:既然重新定義了圖片優(yōu)化的npm腳本命令,那么塌忽,是否需要去掉之前在webpack.config.js
中的image-webpakc-loader
拍埠,當(dāng)然不需要。主要有兩個(gè)原因土居,一個(gè)是sprite雪碧圖
它是用幾張小圖片合成了一張大圖片枣购,這張合成的圖片還需要優(yōu)化嬉探;另一個(gè)是因?yàn)楸卷?xiàng)目對(duì)于存放圖片的目錄進(jìn)行了細(xì)化。
字體
在web開發(fā)中棉圈,自定義的字體也是比較常見的涩堤,在webpack中它的處理和圖片類似,都是使用的 url-loader
和 file-loader
分瘾。參考代碼如下:
...
{
include: path.resolve(__dirname, 'assets/fonts/'),
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
use: [{
loader: 'url-loader',
options: {
limit: 10000,
name: isDev ? '[name].[ext]' : '[name].[hash].[ext]',
outputPath: 'assets/fonts/'
}
}]
},
...
新創(chuàng)建了一個(gè)fonts
目錄又來存放項(xiàng)目開發(fā)過程中使用的字體定躏。
源代碼
此后,webpack構(gòu)建多頁面應(yīng)用系列文章的源代碼芹敌,都在這個(gè)github項(xiàng)目中痊远,webpack3.x multi-page不再維護(hù)。