之前在使用webpack3构建基于less预处理的项目时,在对指定的元素使用background-image: url(xxx)来设置背景图片时,本地开发是ok的,但是在项目编译产出后背景图片就找不到;目前用webpack4开发项目时,同样遇到类似的问题;所以就借此机会探讨一下产生问题的原因。

问题产生原因

webpack3项目场景复现

项目webpack有关css的配置伪码如下:

output: { // 项目编译输出路径
path: path.resolve(__dirname, 'dist')
}
// 图片的loader的配置如下:
{
test: /\.(gif|png|jpe?g)(\?\S*)?$/,
loader: 'url-loader',
options: {
limit: 3000,
name: path.join('static', env === 'development' ? 'img/[name].[ext]' : 'img/[name]_[hash:7].[ext]')
}
} // 样式文件打包产出的文件配置如下:
if (env === 'produdtion') {
webpackCfg.plugins.push(
new ExtractTextPlugin({
filename: 'static/index_[contenthash:7].css',
disable: false,
allChunks: true
})
)
}

上面配置的css在生产环境用extract-text-webpack-plugin来产出css样式文件,开发环境通过style-loader将css内容内联到html文档中;而图片是大于指定的limit大小就打包输出文件。

此时在我们的index.less文件中设置body的背景图片如下:

body {
background-image: url('./img/bg.png');
}

此时本地开发可以看到背景图片,而编译产出css的文件,背景图片地址不能正确加载,通过测试发现是图片路径出现问题,如下图:

从产出的css文件内容来看,body元素的background-image的图片url相对地址是webpack配置产出图片路径,但是页面实际展示时却发现图片路径为:/xx/../dist/static/static/img/bg_ebdbe98.png。

为什么会背景图片路径会多了一个static前缀?查询资料发现:

css文件中设置的background-image的url相对地址是相对于当前css文件目录来得到的

因为,项目中设置css的产出路径为dist/static/index_[contenthash:7].css,而url中经webpack处理后的url相对地址为static/img/bg_[hash:7].png; 这样根据上述规则,图片实际加载地址为即dist/static/static/img/bg_[hash:7].png,导致会在图片路径前缀多加了个static目录。

而为啥本地开发环境没有出现问题,这是因为本地开发环境产出的css样式内容通过style-loader内联到html文档中,这是背景图片的路径是相对于html文档目录,所以是正确的。

webpack4项目场景复现

webpack4项目与webpack3项目不同的地方是,webpack4项目中使用mini-css-extract-plugin插件来处理css样式产出,其改善extract-text-webpack-plugin中的一些问题,其中比较重要的一点是可以使用css的热加载功能。项目中有关css抽出的配置如下:

plugins: [
new MiniCssExtractPlugin({
filename: env === 'production' ? 'static/index.[contenthash:7].css' : 'static/index.css'
})
],
module: {
rules: [{
test: /\.less$/,
use: [
{loader: MiniCssExtractPlugin.loader},
{loader: 'css-loader', options: {...} },
{loader: 'less-loader', options: {...} }
}]
}

webpack4项目在开发环境和生产环境都使用mini-css-extract-plugin插件,所以项目都会产出css文件,二者环境都会出现问题;

解决方法

在知道问题产生原因后,也就知道该如何解决问题了。最佳的解决方法如下:

  • webpack3在extract-text-webpack-plugin的extract方法中单独配置css文件的publicPath

若没有在extract-text-webpack-plugin配置css的publicPath,则会使用webpack.output.publicPath中值;一旦配置值则css中路径就会相对于新配置的publicPath值。但是这个值配置也是需要注意的。例如,上面文件产出目录:

dist
│ index.html
└───static
│ │ index.js
│ │ index.css
│ └─img
│ │ bg.png

图片的地址为static/img/bg.png,而在index.css中引入了该图片地址,所以图片的相对地址是相对于该css文件的目录,及最终加载的图片地址为static/static/img/bg.png,从而导致错误。此时正确的配置extract-text-webpack-plugin如下:

ExtractTextPlugin.extract({
fallback: 'style-loader',
use: loaders,
publicPath: '../'
});

这样,publicPath: '../'配置则是从当前index.css文件的父目录来查找图片。最终url的路径变成 "../static/img/bg.png"。

  • webpack4在mini-css-extract-plugin的loader中配置publicPath

webpack4也是配置publicPath,只不过配置方式稍有不同,如下:

module: {
rules: [
{
test: /\.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../',
hmr: process.env.NODE_ENV === 'development',
},
},
'css-loader',
],
},
],
},

参考文献

webpack生成的css文件background-image url图片无法加载的更多相关文章

  1. vue webpack打包后.css文件里面的背景图片路径错误解决方法

    资源相对引用路径 问题描述 一般情况下,通过webpack+vuecli默认打包的css.js等资源,路径都是绝对的. 但当部署到带有文件夹的项目中,这种绝对路径就会出现问题,因为把配置的static ...

  2. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  3. CSS和JavaScript以及Ajax实现预加载图片的方法及优缺点分析

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画 廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发 ...

  4. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法(转)

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  5. Javascript图片预加载详解 分类: JavaScript HTML+CSS 2015-05-29 11:01 768人阅读 评论(0) 收藏

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  6. 利用CSS、JavaScript及Ajax实现图片预加载的三大方法及优缺点分析

    预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...

  7. webpack快速入门——CSS文件打包

    1.在src下新建css文件,在css文件下新建index.css文件,输入以下代码 body{ background:pink; color:yellowgreen; } 2.css建立好后,需要引 ...

  8. 动态加载/删除css文件以及图片预加载

    动态加载/删除css文件以及图片预加载   功能模块页面   最近,工作中遇到了一个比较奇葩的需求:要在一个页面(PC端)增加一个功能模块,但是这个页面在不久之后要重构,为了新增加的模块可以继续复用, ...

  9. 从输入 URL 到页面加载完成的过程中都发生了什么

    从输入 URL 到页面加载完成的过程中都发生了什么 过程描述 浏览器查找域名对应的 IP 地址: 浏览器根据 IP 地址与服务器建立 socket 连接: 浏览器与服务器通信: 浏览器请求,服务器处理 ...

随机推荐

  1. python基础-网络编程part02

    TCP协议 TCP是传输控制协议,建立双向通道. 三次握手,建立连接 客户端向服务端发送建立连接的请求 服务端接收请求返回确认信息给客户端,并向客户端发送建立连接的请求 客户端接收请求返回确认信息给服 ...

  2. 08-kubernetes 存储卷

    目录 存储卷 emptyDir 测试及使用 Pod测试挂在共享NFS 写测试清单 测试 pv, pvc 创建几个PV 创建测试的Pod 和 PVC 存储卷 分为四种: 有状态,需要存储 有状态,无需存 ...

  3. CentOS 7 Cobbler 安装

    Cobbler介绍 Cobbler是一个Linux服务器快速网络安装的服务,而且在经过调整也可以支持网络安装windows. 使用python开发,小巧轻便(才15k行python代码),可以通过网络 ...

  4. 机器学习十大算法总览(含Python3.X和R语言代码)

    引言 一监督学习 二无监督学习 三强化学习 四通用机器学习算法列表 线性回归Linear Regression 逻辑回归Logistic Regression 决策树Decision Tree 支持向 ...

  5. 失去循环标记的Python,我这样实现跳出外层循环

    不完美的Python 自从各类Python大火,感觉天上地下哪儿都有Python的一席之地,Python功夫好啊-但python有些细节上缺少其他语言的便利.今天我们就来举几个例子. 跳出外层循环 大 ...

  6. 补习系列(20)-大话 WebSocket 与 "尬聊"的实现

    目录 一.聊聊 WebSocket 二.Stomp 是个什么鬼 三.SpringBoot 整合 WebSocket A. 引入依赖 B. WebSocket 配置 C. 控制器 D. 前端实现 四.参 ...

  7. 转:SQL SERVER 2014 安装图解(含 SQL SERVER 2014 安装程序共享)

    开篇介绍 2015年1月1日,新的一年开始之际,本来应该好好做点有意义的事情来跨个年的.结果,老习惯 - 睡觉之前一定要折腾一下电脑,说干就干,给新到的 DELL 电脑装虚机,下载 SQL SERVE ...

  8. 利用python实现dll依赖关系导出

    #说明:遍历rootdir目录下所有dll,导出每个dll依赖的dll信息到dstdir目录下 # 配合NotePad++打开所有txt,搜索,可快速定位到某dll被依赖的所有dll文件 import ...

  9. UITableView 实例详解 滑动编辑 headerView

    转自:http://blog.csdn.net/reylen/article/details/8505960 self.dataArray = [[[NSMutableArray alloc]init ...

  10. 第四章 JavaScript对象及初始面向对象

    创建对象: //方式一 var ower=new Object(); ower.name="长春花"; ower.genera="夹竹挑科 长春花属"; owe ...