url-loader处理css中的图片资源遇到的问题

处理css中的图片资源时,我们常用的两种loader是file-loader或者url-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'

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方式让用户访问,所有前端文件都放置于

http://localhost:63342/url-loader-test/dist/

那么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即可。

    推荐文档:

    file-loader: https://github.com/webpack-contrib/file-loader

    url-loader: http://www.cnblogs.com/ghost-xyx/p/5812902.html

2.loader中的参数

    上面提到url-loader的参数和file-loader的参数,那么loader的参数是个什么概念呢?loader的参数用来自定义loader处理文件时的工作特性。下面以url-loader为例,介绍一下webpack的loader中的参数。

    首先看下面的例子:

module.exports = {
    // 入口文件路径,__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的参数

    先看下配置好的代码:

module.exports = {
    // 入口文件路径,__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: 'url-loader?limit=1024&name=[path][name].[ext]&outputPath=img/&publicPath=output/',
            }
        ]
    }
}

    这里涉及到了4个参数:limit、name、outputPath、publicPath。其中limit已经说明过。file-loader相关的是name、outputPath和publicPath。下面解释一下这3个参数
    name表示输出的文件名规则,如果不添加这个参数,输出的就是默认值:文件哈希。加上[path]表示输出文件的相对路径与当前文件相对路径相同,加上[name].[ext]则表示输出文件的名字和扩展名与当前相同。加上[path]这个参数后,打包后文件中引用文件的路径也会加上这个相对路径。

    outputPath表示输出文件路径前缀。图片经过url-loader打包都会打包到指定的输出文件夹下。但是我们可以指定图片在输出文件夹下的路径。比如outputPath=img/,图片被打包时,就会在输出文件夹下新建(如果没有)一个名为img的文件夹,把图片放到里面。

    publicPath表示打包文件中引用文件的路径前缀,如果你的图片存放在CDN上,那么你上线时可以加上这个参数,值为CDN地址,这样就可以让项目上线后的资源引用路径指向CDN了。

4.安装url-loader

npm install --save-dev url-loader

5.demo
https://github.com/KIDFUCKER/webpack-demo.git

来源:网络


智能推荐

游戏开发中图片模糊、锯齿相关问题的处理

目录   引言: 常见的图片显示失真情况: 处理办法: 总结: 引言: 在游戏开发中经常会碰到一个比较头疼的问题。“明明美术出的图很好看很清晰,放到游戏里就糊了、或者有锯齿看着很难受”。 尤其是做手机游戏,因为要适配各种性能配置的手机。往往对资源要进行压缩处理来减小包体和内存的占用。 针对这些糊了、锯齿等现象一般的处理就是根据经验去切换压缩类型、换高清图、打开引擎...

vue项目中遇到的打印,以及处理重新排版后不显示echarts图片问题。

1. 项目中用到的打印 页面: css: 控制好宽度一般A4 我调试的是794px多了放不下,小了填不满。当时多页打印的时候,一定要控制好每一个页面内容显示的高度不要超过一个页面,当然根据自己项目来。 由于我的项目是每一个页面固定一个页尾部,所以当显示的时候正常排版显示。但是一旦点击了打印预览需要修改这个区域的css让他固定在每一个页面的底部。   js代码,点击打印后执行(如果右键点击...

关于css中touch-action属性 在移动端开发中遇到的问题

初次接触 第一次接触touch-action这个属性 是在之前一个网约车公众号项目中遇到的 当时采用的是vue做框架 cube-ui做组件库 当时在版本迭代的时候增加了余额支付的功能 需要一个密码键盘 种种原因没有引入第三方插件  而是选择了手写 样式如下图: 当连续快速点击某个数字时,在ios端出现了强制缩放,百度一圈发现了这个属性, *{touch-action: manipulat...

MATLAB读取图片遇到长宽的问题

fid = fopen('BQMall_832x480_60.yuv','r'); row=480;col=832;   Y=fread(fid,[col,row],'uint8');   %行和列不能混 U=fread(fid,[col/2,row/2],'uint8'); V=fread(fid,[col/2,row/2],'uint8');  imsh...

Windows遇到的图片查看问题。

解决windows照片查看器打不开图片,可能由于内存不足的问题。 问题显示如图 问题原因: 可能是由于windows照片查看器识别处理不了该图片的颜色。 解决方案: 控制面板–>查看方式:小图标–>颜色管理 颜色管理–>高级–>设备配置文件:Agfa:Swop Standard。...

猜你喜欢

fastDFS上传图片时遇到的问题

总结在项目中使用fastDFS会遇到的错误 一:配置文件没有写全 解决方法:该报错表示没有配置(multipartResolver)Bean,检查配置文件,发现在配置文件中没有添加该配置 二:前端上传图片时的请求格式发送错误 解决办法:(angular写法)...

react写上传图片遇到的问题

今天在公司写上传图片, 偶然发现element和antd的upload的组件内部都是默认通过ajax帮你发的请求,难道只预留了一个action属性给给你传 不过这样有个问题,就是上传图片接口,你就只能传一个字段了,因为默认帮你调的 所以我就自己写了upload组件,反正都是基于input type="file" 写出来到后面都没什么问题 但是有个问题出现了 项目里发请求是封装的...

夜光带你走进通信网络(十五) 新的领域

夜光序言: 你能否做我的不息白昼 不然我的黑夜熬不到头     正文:错误控制:自动重发请求   在数据链路层,错误控制主要是指错误检测和重传机制。   在一次交互中出现任何一个错误,一个否定应答(NAK)就被返回并且对应的帧就被重新传输,这个过程称为自动重发请求(ARQ)。一般有三种情况下的数据重传:帧破坏,帧丢失,以及应答帧丢失    ...

安装anaconda并创建一个tensorflow环境的详细教程

安装Anaconda并创建tensorflow环境超级详细教程 二话不说先上资源链接: 百度云盘链接地址: https://pan.baidu.com/s/1Me9cLJ5LRhxuDmXoLkOIjA 提取码:yq23 (此版本为本人将要演示的安装版本) 如果感觉此版本不太符合自己的要求,接着来地址: 清华镜像园地址如下: https://mirrors.tuna.tsinghua.edu.cn...

如何修改桌面<Desktop>路径

如何修改桌面<Desktop>路径 修改桌面路径有什么好处?咳...为了不再享受C盘爆掉的快乐~ 本人懒人一枚,文件喜欢扔桌面,扔着扔着C盘就要炸了,于是乎,开始霍霍桌面路径嘎嘎嘎嘎嘎嘎~ 打开此电脑 此电脑   找到桌面图标 此电脑-桌面​​​​   右键桌面图标单击属性 桌面-属性   点击位置 属性-位置   在位置面板中点击移动 位置-移...

问答精选

iPhone jQuery actions with drag and drop

I'm trying to achieve the following. When a user drags an icon to a specific location in the html page and keeps it for about 3 seconds it must create automatically a new page (if there is no page) ot...

writeAsCSV() and writeAsText() is unexpected

I am using apache flink via the Scala API and at some point I obtain a DataSet[(Int, Int, Int)]. The result of using the methods writeAsCSV() and writeAsText() is unexpected. It creates a directory. T...

MySQL having if

I'm having trouble with a MySQL query. If the label is "5" then I only want records where there is more than 10 of them for the current day, but any number of rows for other labels. What is ...

How to parse out JavaScript from arbitrary HTML

I'm using jericho for sanitizing html and it works great. Except in one situation I can't figure out. I want to completely remove any script and the script content. Right now I'm getting the script ta...

How can I toggle a boolean based on keyboard input?

So, I'm trying to create a simple autoclicker in python, just for fun. I've downloaded and experimented with two libraries, PYAutoGUI and Keyboard. I can turn on the autoclicker, but can't turn it off...

相关问题

相关文章

热门文章

推荐文章

相关标签

推荐问答