我們使用webpack打包專案中,在處理圖片路徑時, 最常用的loader有兩種, url-loader 和 file-loader。
我們在寫專案中引用路徑的時候,填寫的URL是基於我們開發時的路徑, 但是在webpack打包時, 會將各個模組打包成一個檔案,裡面引用的路徑是相對於入口html檔案,並不是相對於我們的原始檔案路徑的。loader 可以解析專案中引入的URL,並且根據配置,把圖片拷貝到相應路徑, 再將打包後的檔案中的路徑 替換為影象的最終路徑。
file-loader 和 url-loader 都可以解決這個問題。 但是url-loader會將引入的圖片進行編碼, 我們引用的時候只需要引入這個檔案就可以訪問圖片了, 可以大大減少 HTTP請求的次數。
url-loader 封裝了 file-loader, 但並不依賴他, 所以我們可以只需要安裝 url-loader就可以了。
在使用url-loader時,出現了 路徑引用錯誤的 情況。
- 問題復現
webpack.prod.js
module.exports = {
// ...
rules: [
// ...
{
test: /\.(png|svg|jpg|gif)$/,
use: [
// ...
{
loader: 'url-loader', //是指定使用的loader和loader的配置引數
options: {
limit:500, //是把小於500B的檔案打成Base64的格式,寫入JS
name: 'images/[name]_[hash:7].[ext]',
}
}
]
},
{
test: /\.(css)$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
}
]
],
}
複製程式碼
index.js
import React from 'react';
import ReactDom from 'react-dom';
import './index.scss';
import logo from './logo.png';
ReactDom.render(
<div>Hello world
<img src={logo} />
</div>,
document.getElementById("root")
);
複製程式碼
index.css
#root {
color: aqua;
background: url('./logo.png');
};
複製程式碼
打包後的 css 檔案
#root{background:url(images/logo_e179a47.png);color:#0ff}
複製程式碼
打包後 的 檔案結構
── css
│ └── app.9fd7e730df40df61cc5a.css
├── images
│ └── logo_e179a47.png
├── js
│ └── app.382da24eb9c30ee2.js
└── index.html
我們在瀏覽器中開啟打包後的 index.html
可以看出我們在index.js 中 引入的圖片是可以正常載入的, 但是我們在css中引入的背景圖 並沒有載入成功。
- 問題原因
webpack 在 打包時, 首先會把圖片 複製到 /dist/images/ 資料夾下, 然後把 css 檔案中的url 路徑 替換為webpack中options的name屬性指向的路徑,即 /images/logo.png, 但是這個路徑是相對路徑,是相對於 /dist/css/~.css 來說的, 所以此處引用的 檔案地址為: /dist/css/images/logo.jpg。 但是我們打包後的css 資料夾中, 並沒有 images/logo.png, 所以圖片並沒有渲染出來。 但是 對於 我們 index.js 中 引用的圖片, 此處相對路徑是相對於 index.html 來說的, 所以 是可以取到圖片的。
- 解決方式
{
test: /\.(css)$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
}
},
{
loader: 'css-loader',
}
]
},
複製程式碼
在為css檔案配置 loader時, 新增 publicPath 屬性。 這樣做, 我們在圖片打包時, 仍會將圖片複製在 /dist/images/ 資料夾之下, 但是 在css檔案中引用時, 會將路徑替換為 publicPath + name。
打包後的 css 檔案:
#root{background:url(../images/logo_e179a47.png);color:#0ff}
複製程式碼
至此, 專案中 css 的檔案引用路徑 和 js 中的檔案引用路徑 均為正確的圖片路徑。