之前在使用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. 【JavaEE】之MyBatis查询缓存

    为了减轻数据压力,提高数据库的性能,我们往往会需要使用缓存.MyBatis为我们提供了一级缓存和二级缓存. (1)一级缓存是SqlSession级别的缓存,在操作数据库的时候需要创建一个SqlSess ...

  2. Leecode_137_singleNumberII

    参考: http://blog.csdn.net/jocyln9026/article/details/19397477

  3. 【并发编程】ThreadLocal的兄弟InheritableThreadLocal

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 引子 public class InheritableT ...

  4. 每个开发人员都应该知道的11个Linux命令

    本文主要挑选出读者有必要首先学习的 11 个 Linux 命令,如果不熟悉的读者可以在虚拟机或云服务器上实操下,对于开发人员来说,能熟练掌握 Linux 做一些基本的操作是必要的! 事不宜迟,这里有 ...

  5. gdb调试常用方法介绍

    一.概述   GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具.没有统一的界面,所有的操作都是通过命令的方式进行提供.对于习惯了图形界面方式进行调试的猿猿来说可能不是很顺手,但是如果你在 ...

  6. Java修炼——面向对象的三大特征_多态_多态的三个必要条件

    多态指的是同一个方法调用,由于对象不同可能会有不同的行为,现实生活中,同一个方法,具体实现会完全不同. 多态的要点: 1.多态是方法的多态,不是属性的多态(多态与属性无关) 2.多态的存在有三个必要条 ...

  7. 使用 Zookeeper 的 Api 实现服务订阅

    服务提供者 服务提供者中拷贝 Constants 服务提供者中拷贝 UserService 连接 Zk 集群 /*** * 连接ZooKeeper集群 */ public ZooKeeper conn ...

  8. 学习go语言第二天-变量、常量

    编写测试程序 源码文件以_test结尾;例如:xxx_test.go 测试方法名以Test开头;例如:func TestXXXXX(t *testing.T){} 实现斐波那且数列 package f ...

  9. HDU-3727 Jewel

    Jimmy wants to make a special necklace for his girlfriend. He bought many beads with various sizes, ...

  10. FlyWay工作原理

    本文译自Flyway官方文档,原文地址https://flywaydb.org/getstarted/how 当你最开始将FlyWay指向一个空数据库时. 它会试着去查找schema历史表,如果此时数 ...