url-loader处理css中的图⽚资源遇到的问题
处理css中的图⽚资源时,我们常⽤的两种loader是或者,两者的主要差异在于。url-loader可以设置图⽚⼤⼩限制,当图⽚超过限制时,其表现⾏为等同于file-loader,⽽当图⽚不超过限制时,则会将图⽚以base64的形式打包进css⽂件,以减少请求次数。
本⽂的主要想说的是我们在使⽤file-loader或url-loader时经常出现的图⽚地址错误导致图⽚引⽤不到的情况,及相应解决办法。
场景复现
⼯程⽬录如下
⼯程⽬录
index页⾯⽬录
webpack配置⽂件中,关于图⽚的处理:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[hash:7].[ext]'
}
},
index.js⽂件
import './index.scss'
svg图片怎么使用index.html⽂件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="pic"></div>
</body>
</html>
index.scss⽂件:
.pic{
width:100px;
height:100px;
background: url('./1.jpg');
background-size: 100px 100px;
}
当我们执⾏ npm run build后 查看dist中的情况如下:
我们通过服务 打开index.html会发现页⾯中并没有 图⽚,并且报错:
这是我们当然是要去看看 打包后的 css⽂件中的 图⽚路径了:
.pic{width:100px;height:100px;background:url(img/1.d1efbb3.jpg);background-size:100px 100px}
/*# sourceMappingURL=index.min.css.map?v=7b7c89f8*/
background:url(img/1.d1efbb3.jpg);,index.min.css⽂件竟然去⾃⼰的同级⽬录img⽂件夹,当然不到了还记得我们的 dist⽬录情况么?
很显然img⽂件夹位于index.min.css上层,如果 是background:url(../img/1.d1efbb3.jpg);就对了。
然后我们尝试去修改webpack的配置⽂件,以达到我们的预期:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: '../img/[name].[hash:7].[ext]'
}
},
然后再npm run build
index.min.css 内的 background的图⽚地址的确变成了 我们想要的
.pic{width:100px;height:100px;background:url(../img/1.d1efbb3.jpg);background-size:100px 100px}
/*# sourceMappingURL=index.min.css.map?v=eef74865*/
但是悲剧的是 img 竟然被打包到了 dist⽂件夹的外⾯,不在位于dist内了,所以
是不是很抓狂……看来我们修改配置⽂件的⽅法是不对的。仔细想想,能明⽩其中的原因么?
打包的时候webpack会把 scss⽂件中的 background url 替换成我们webpack配置⽂件中的 options的name属性中设置的内容,同时把 scss⽂件中的 background url 中的图⽚⽂件给复制到 webpack配置⽂件中的 options的name属性所指向路径下,关键就在这⾥了。
webpack配置⽂件中的 options的name属性所指向路径是相对路径,那么这个路径到底是相对于谁呢?你仔细观察会发现它是相对于 dist ⽂件夹的,也就是webpack的出⼝路径。举个例⼦:
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[hash:7].[ext]'
}
},
上⾯的配置,就会把图⽚给复制到dist/img/1.jpg,然后将index.min.css 你的 background属性改
为background:url('img/1.png'),该路径也是相对路径,但是它不相对于 dist,⽽是相对于dist/css,因为我的css⽂件并没有被输出到 dist的直接路径下,⽽是输出到了dist/css下,所以css ⽂件就会去dist/css/img/1.png去拿图⽚,但是图⽚却位于dist/img/1.png,这就最终导致了 css⽂件不到图⽚。
配置⽂件复制图⽚是相对于 webpack 出⼝路径的, css⽂件引⽤图⽚是相对于css⽂件所在路径的,如果这两个
路径相同也就是 webpack出⼝路径 = css⽂件所在路径那么很幸运,你的图⽚是可以到的。但是⼀般情况下是不同的,我们习惯于将出⼝路径定为dist/ 然后将css⽂件输出到 'dist/css/' ,最终导致了引⽤不到图⽚的结果。
⾄此原因分析完毕。
解决⽅法:
在配置项内加⼊ publicPath 属性,设置为部署时的绝对路径
⽐如所 以后你的页⾯ 会通过如下url⽅式让⽤户访问,所有前端⽂件都放置于
那么pubilcPath的 值就应该是 '/url-loader-test/dist/',也就是你的部署接⼝地址。
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: 'img/[name].[hash:7].[ext]',
publicPath:"/url-loader-test/dist/"      //该地址不是唯⼀的,根据你的代码实际路由地址进⾏修改
}
},
这样做的原因是,webpack打包时,还会将图⽚复制到 dist/img/1.png,但是他会把css⽂件中的background url 改写为 publicPath + name ,本例中最后⽣成的index.min.css 如下:
.pic{width:100px;height:100px;background:url(/url-loader-test/dist/img/1.d1efbb3.jpg);background-size:100px 100px}
/*# sourceMappingURL=index.min.css.map?v=eef74865*/
这时css⽂件中的url 地址就变成了⼀个绝对 路由。
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
如果我们希望在页⾯引⼊图⽚(包括img的src和background的url)。当我们基于webpack进⾏开发时,引⼊图⽚会遇到⼀些问题。
其中⼀个就是引⽤路径的问题。拿background样式⽤url引⼊背景图来说,我们都知道,webpack最终会将各个模块打包成⼀个⽂件,因此我们样式中的url路径是相对⼊⼝html页⾯的,⽽不是相对于原始css⽂件所在的路径的。这就会导致图⽚引⼊失败。这个问题是⽤file-loader解决的,file-loader可以解析项⽬中的url引⼊(不仅限于css),根据我们的配置,将图⽚拷贝到相应的路径,再根据我们的配置,修
改打包后⽂件引⽤路径,使之指向正确的⽂件。
另外,如果图⽚较多,会发很多http请求,会降低页⾯性能。这个问题可以通过url-loader解决。url-loader会将引⼊的图⽚编码,⽣成dataURl。相当于把图⽚数据翻译成⼀串字符。再把这串字符打包到⽂件中,最终只需要引⼊这个⽂件就能访问图⽚了。当然,如果图⽚较⼤,编码会消耗性能。因此url-loader提供了⼀个limit参数,⼩于limit字节的⽂件会被转为DataURl,⼤于limit的还会使⽤file-loader进⾏copy。
url-loader和file-loader是什么关系呢?简答地说,url-loader封装了file-loader。url-loader不依赖于file-loader,即使⽤url-loader 时,只需要安装url-loader即可,不需要安装file-loader,因为url-loader内置了file-loader。通过上⾯的介绍,我们可以看到,url-loader ⼯作分两种情况:1.⽂件⼤⼩⼩于limit参数,url-loader将会把⽂件转为DataURL;2.⽂件⼤⼩⼤于limit,url-loader会调⽤file-loader进⾏处理,参数也会直接传给file-loader。因此我们只需要安装url-loader即可。
推荐⽂档:
2.loader中的参数
上⾯提到url-loader的参数和file-loader的参数,那么loader的参数是个什么概念呢?loader的参数⽤来⾃定义loader处理⽂件时的⼯作特性。下⾯以url-loader为例,介绍⼀下webpack的loader中的参数。
⾸先看下⾯的例⼦:
// ⼊⼝⽂件路径,__dirname是根⽬录
entry: __dirname + '/src/main.js',
// 打包⽣成⽂件
output: {
path: __dirname + '/output',
filename: 'main.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.jpeg$/,
use: [
{
loader: 'url-loader',
options: {
limit: '1024'
}
},
]
}
]
}
}
其中,url-loader的配置中的options属性表⽰的就是url-loader的参数,还有⼀种等价的写法:
{
test: /\.jpeg$/,
use: 'url-loader?limit=1024
}
如果有多个参数,就⽤ ‘&’ 连接起来。和http请求中的参数类似。正如前⾯介绍的,limit这个参数就是告诉url-loader,在⽂件⼩于多少个字节时,将⽂件编码并返回DataURL。此外url-loader还有⼀些⽤于file-loader的参数。我们知道,file-loader的作⽤是将⽂件复制到其他⽬录。file-loader提供了⼀系列参数允许我们⾃定义诸如输出⽂件、⽂件名规则、发布路径等特性的参数。下⾯介绍⼀下这些参数。
3.url-loader的参数
先看下配置好的代码:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。