在以前的系列文章中,我已經介紹瞭如何用webpack實現多頁面應用
的js,html,css的處理。今天就主要介紹如何處理靜態資源,在web開發中最多見的靜態資源就是圖片。css
而由於在web中,圖片有兩種主要的引入方式,第一種是<img src="...">
,第二種是backgorund-image: url(...)
。前者在html中使用,後者在css中使用。html
圖片常見的類型有jp(e)g,png,gif,包括如今廣泛使用的svg以及webp。svg做爲矢量圖形,有必定的使用場景,而webp做爲將來web開發的趨勢,有必定的使用場景,好比:愛奇藝中的輪播圖(carousel)中就是用webp,但其餘的見到的很少。node
如今,web開發中使用最多的仍是jpg和png,處理他們,在構建工具中使用url-loader
和file-loader
就行了,其中file-loader負責圖片的拷貝和輸出,並會給圖片名添加一個hash值。webpack
說到這裏,不少人會想到字體圖標
。之前處理web頁面中的圖標(icon),使用圖片來處理,這樣會帶來一個性能問題就是http請求的增多,這樣會形成服務器的負載壓力,同時會帶來用戶體驗的問題,由於會出現頁面的局部空白和頁面重繪的問題,固然一種解決方案使雪碧圖(sprite),可是若是圖片過大怎麼解決,如何對圖片進行分解(大變小的問題),圖片的拼接比較困難,最要命的是在引用雪碧圖時要進行計算,除此以外就是如何對雪碧圖的組成圖片進行自定義的刪減,而使用字體圖標這些問題,都會獲得必定程度的解決,固然在構建工具中可使用webpack-spritesmith
這個插件來處理組成雪碧圖的圖片。css3
固然,有些特殊的狀況,須要使用base64
,這裏使用url-loader
便可。git
將圖片處理爲base64有使用場景,將圖片轉換爲雪碧圖亦有使用場景,單獨的圖片處理也有使用場景(這些使用場景的圖片大小從左到右依次增大)。github
這些場景在一個web項目中都會涉及到。web
雖然使用字體圖標能夠替代雪碧圖,由於字體圖標有更小的尺寸,更自由的操做手法(如:圖標顏色的自定義),可是一個DIY的web項目仍是有些圖標仍是須要雪碧圖。npm
可是,這裏有一個問題,如何在一個項目中同時使用base64,雪碧圖,字體圖標,單獨的圖片。json
在構建多頁面應用中,如何解決呢?
處理字體圖標很簡單,如:iconfont(阿里巴巴字體圖標庫),就像引用css那麼簡單。
base64的處理,使用url-loader
。
雪碧圖的處理,可以使用webpack-spritesmith
這個插件
使用file-loader
,它負責拷貝url-loader
的處理結果,並輸出。
上面就是咱們常見的圖片處理,若是要處理svg能夠參考svg-url-loader
,若是要處理webp能夠參考webp-loader
對圖片進行優化,會帶來良好的用戶體驗。
熟悉圖片優化的都知道漸進式(progressive),可參考nuwen.net
jp(e)g能夠進行連續性
處理,這樣可保證圖片數據請求回來多少,就渲染多少,是自上而下的渲染,也是有模糊到清晰的狀態。
png能夠進行交叉
處理,這樣也可保證圖片數據請求回來多少,就渲染多少,它是總體的顯示,並且是又模糊狀態到清晰的狀態。
gif圖片通常使用小圖,若是是大圖會記號瀏覽器性能,還不如使用視頻,或者用css動畫來代替。我我的整理了一個css 動畫集,有須要的能夠看一下。
在構建多頁面應用中,會使用到image-webpack-loader
來作優化處理。
其中,配置項options
中的mozjpeg
處理jp(e)g圖片,pngquant
處理png圖片,gifsicle
處理gif圖片,webp
處理webp圖片。
首先,看一下多頁面應用中的目錄結構圖:
./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
跟之前的實例代碼相比,此次的文件目錄結構變化較大,這裏將要處理的全部文件模塊都放在了src
目錄下。
可能有人會問,爲何要要將目錄分的這麼細,下面我就說一下爲何這麼分。
aboutUs.js
, contactUs.js
, index.js
, recruitment.js
是四個路由頁面,要用到的js代碼,css.js
處理各個路由頁面公用的css代碼;productus
存放產品模塊代碼,根據開發的須要能夠建立其餘的模塊目錄,目錄結構相似於commons
中的header
模塊,其中utils
放置本身總結的工具模塊代碼,如table
,form
等。而後,指定style-loader
,css-loader
等樣式相關的loader處理css樣式文件,這樣能夠減小遍歷,縮短構建時間。base64
,sprite
,ohter
等,爲何要這樣分?若是分的話file-loader
這個webapck的loader會複製並導出imgs
目下全部的圖片,者在構建中並非咱們須要的,這樣會增長構建的時間。若是讓url-loader
處理base64
目錄下的圖片,file-loader
處理ohter
目錄下的圖片,webpack-spritesmith
處理sprite
目錄下的圖片,並將生成的圖片放到ohter
目錄下,用file-loader
進行二次處理。這樣作,webpack處理更精確,能夠減小沒必要要的遍歷,極大地減小構建的時間,一樣方便對圖片的管理,特別是對於須要改變sprite
的圖片的管理。imgs
目錄下建立base64
目錄,sprite
目錄,使用file-loader
指定處理ohter
目錄,是爲了不file-loader將全部的圖片都拷貝一份並導出到dist
輸出目錄中,由於與base64
相關的文件已經在css
樣式文件中了,再拷貝一份,已經沒有意義,而sprite
相關的文件會被webpack-spritesmith
插件先處理生成一個文件,因此再拷貝它們也沒有意義,還會讓構建速度更慢。page
目錄下,放置全部的html代碼塊(這裏使用pug編譯器生成相應的html代碼塊),它的目錄分類和css
相相似,它們是一一對應的關係。注意:iamge-webpack-loader
,要先對全部的圖片進行優化處理,而後再用其餘loader處理。loader的執行順序,若是你是style-loader!css-loader!sass-loader"
使用,它是從右到左方向前後執行,若是你是在配置文件中的rules: [...]
數組中,它也是從右到左的方向執行,若是你將全部的loader規則有回車符號隔開,那麼它就是自下而上的執行。
針對<img src="...">
的圖片使用,ul-loader
是不會處理html中的img引用,如今處理這樣狀況的loader或插件,也並無一個比較出名的。如今通用的作法就是將圖片拷貝一份到生成目錄中,copy-webpack-plugin
。參考配置代碼以下:
new CopyWebpackPlugin([ { from: path.resolve(__dirname, 'assets/imgs/other/'), to: path.resolve(__dirname, 'dist/assets/imgs/other/'), ignore: ['.*'] } ]),
但這樣,會帶來另外一個問題就是圖片的優化問題,如何使用 image-webpack-loader
?原本的目的是對項目中使用到的全部的圖片進行優化,而如今只能對base64
和sprite
目錄下的圖片進行優化處理。不過,不要慌,能夠經過建立一個新的npm腳本命令(本是裏使用的是npm run img
)來對圖片進行壓縮處理,新建了一個目錄static
用來保存優化前的圖片,ohter
用來保存優化後的圖片。
首先,須要安裝imagemin
, imagemin-mozjpeg
, imagemin-optipng
, imagemin-gifsicle
:
yarn add imagemin imagemin-mozjpeg imagemin-optipng imagemin-gifsicle --dev
而後,在項目的根目錄添加一個優化圖片的文件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('圖片優化完成!'); })();
最後,在package.json
文件中添加以下的npm命令:
... "scripts": { ... "img": "node optzing-img.js" }, ...
在控制輸入npm run img
,而後按下回車鍵就能夠獲得你所須要的。
注:既然從新定義了圖片優化的npm腳本命令,那麼,是否須要去掉以前在webpack.config.js
中的image-webpakc-loader
,固然不須要。主要有兩個緣由,一個是sprite雪碧圖
它是用幾張小圖片合成了一張大圖片,這張合成的圖片還須要優化;另外一個是由於本項目對於存放圖片的目錄進行了細化。
在web開發中,自定義的字體也是比較常見的,在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/' } }] }, ...
新建立了一個fonts
目錄又來存放項目開發過程當中使用的字體。
此後,webpack構建多頁面應用系列文章的源代碼,都在這個github項目中,webpack3.x multi-page再也不維護。