咱们使用webpack打包项目中,在处理图片路径时, 最经常使用的loader有两种, url-loader 和 file-loader。css
咱们在写项目中引用路径的时候,填写的URL是基于咱们开发时的路径, 可是在webpack打包时, 会将各个模块打包成一个文件,里面引用的路径是相对于入口html文件,并非相对于咱们的原始文件路径的。loader 能够解析项目中引入的URL,而且根据配置,把图片拷贝到相应路径, 再将打包后的文件中的路径 替换为图像的最终路径。html
file-loader 和 url-loader 均可以解决这个问题。 可是url-loader会将引入的图片进行编码, 咱们引用的时候只须要引入这个文件就能够访问图片了, 能够大大减小 HTTP请求的次数。react
url-loader 封装了 file-loader, 但并不依赖他, 因此咱们能够只须要安装 url-loader就能够了。webpack
在使用url-loader时,出现了 路径引用错误的 状况。web
- 问题复现
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.jsbash
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.cssapp
#root { color: aqua; background: url('./logo.png'); }; 复制代码
打包后的 css 文件dom
#root{background:url(images/logo_e179a47.png);color:#0ff} 复制代码
打包后 的 文件结构svg
── 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 中的文件引用路径 均为正确的图片路径。