圖片的引入方式
圖片是前端項目必不可少的靜態資源,在日常開發中,我們可能會在下面三種情況使用圖片:
1.HTML 中通過img標簽等方式引入;
2.CSS 中通過src等方式引入;
3.JavaScript 中使用圖片的 URL 或者內容(比如 Canvas 等);
最笨最直接的方式就是直接寫死線上的地址,例如在頁面中,我們引入
如下:
<img src=”http://cdn.example.com/public/logo.png” />
上面地址的 http://cdn.example.com 是一個 CDN 靜態域名,后面是我們完整的路徑,這樣我們上線的時候地址就可以直接看了,我們線下開發的時候可以提前將靜態資源打包好上傳到線上。這樣操作想想就很費勁,而且 CDN 每次靜態資源更新都要需要刷新緩存,如果我們使用 MD5 命名圖片的時候就更麻煩了。
我們在 Webpack 中,則可以使用 loader 的方式完成圖片的引入。例如在 CSS 文件中,直接相對路徑使用背景圖片:
.bg-img{
backgroud: url('./public/logo.png') no-repeat;
}
在 HTML 中也可以直接使用相對路徑:
<img src=”./public/logo.png” />
還記得我們之前學過的resolve.alias方式創建一個目錄的alias引用,這種方式不僅僅可以在 JavaScript 中使用,在 HTML 和 CSS 中也可以使用的:
// webpack.config.js
module.exports = {
resolve: {
alias: {
'@assets': Path2D.resolve('./src/assets')
}
}
}
<img src=”@assets/public/logo.png” />
使用 loader 來加載圖片資源
怎么使用圖片我們了解了,但是怎么讓 Webpack 識別圖片,並且能夠打包輸出呢?這時候就需要借助 loader 了,這里有兩個 loader 可以使用:file-loader 和 url-loader 。
file-loader和url-loader是經常在一些 Webpack 配置中看到的兩個 loader,並且兩個 loader 在一定應用場景上是可以相互替代的,但是對於兩者的區別,很少有人能夠說得清楚,下面介紹下兩者的區別。
- file-loader:能夠根據配置項復制使用到的資源(不局限於圖片)到構建之后的文件夾,並且能夠更改對應的鏈接;
- url-loader:包含 file-loader 的全部功能,並且能夠根據配置將符合配置的文件轉換成 Base64 方式引入,將小體積的圖片 Base64 引入項目可以減少 http 請求,也是一個前端常用的優化方式。
下面以url-loader為例說明下 Webpack 中使用方法。首先是安裝對應的 loader:
npm install -D url-loader
下面我們創建一個項目,目錄結構如下:
|---- package.json # npm package.json
|---- src
| |---- assets # 靜態資源
| |---- img # 圖片資源
| |---- large.png # 大圖片 超過 1M
| |---- small-01.png # 小圖圖片
| |---- small-02.png # 大圖片 超過 1M
| |---- small-03.png # 大圖片 超過 1M
| |---- index.css # css 文件
| |---- index.html # html
| |---- index.js # js
|---- webpack.config.js # webpack 配置
首先我們在index.css中引入 small-01.png:
.bg-img{
backgroud: url(./assets/img/small.png) no-repeat;
}
然后在index.js中引入了index.css和large.png:
import img from './assets/img/large.png'
import style from './index.css'
console.log(img, style);
最后我們在index.html中通過 img 引入large.png:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<img src="./assets/img/large.png" alt="背景圖">
</body>
</html>
這時候我們修改webpack.config.js:
const HTMLPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './srcindex.js',
devtool: false,
module: {
rules: [
{
test: /\.html$/,
use: ['html-loader']
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.(png|svg|jpg|gif)$/,
use: {
loader: 'url-loader'
}
}
]
},
plugins: [
new HTMLPlugin({
template: './src/index.html'
})
]
}
執行webpack后發現,打包出來的文件都比較大,通過查看內容發現,我們的圖片被Base64處理了,然后直接引入了。
這是因為url-loader本身優先是將資源Base64引入的。雖然圖片Base64可以減少 http 請求,但是對於1M+這么大的圖片都Base64處理,范圍增加了 CSS、JavaScript 等文件的大小,而且將這么大的Base64反解成可以使用的圖片渲染出來,時間消耗也是很大的。
所以這時候需要使用url-loader的limit選項來控制不超過一定限制的圖片才使用Base64:
{
test: /\.(png|svg|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
imit: 3*1024
}
}
}
這時候再執行webpack,發現多打出一個ad19429dc9b3ac2745c760bb1f460892.png的圖片,這張圖片就是large.png的圖片,因為超過了limit=3*1024顯示所以沒有被處理成Base64。
繼續查看index.html和main.js(index.js打包出來的文件),發現我們使用large.png的地址都被 Webpack 自動替換成了新的路徑ad19429dc9b3ac2745c760bb1f460892.png。
配置 CDN 域名
一般靜態資源上線的時候都會放到 CDN,假設我們的 CDN 域名和路徑為:http://bd.bxstatic.com/img/,這時候只需要修改output.publicPath即可。
