webpack生成的css文件background-image url图片无法加载
之前在使用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图片无法加载的更多相关文章
- vue webpack打包后.css文件里面的背景图片路径错误解决方法
资源相对引用路径 问题描述 一般情况下,通过webpack+vuecli默认打包的css.js等资源,路径都是绝对的. 但当部署到带有文件夹的项目中,这种绝对路径就会出现问题,因为把配置的static ...
- 利用CSS、JavaScript及Ajax实现图片预加载的三大方法
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- CSS和JavaScript以及Ajax实现预加载图片的方法及优缺点分析
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画 廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发 ...
- 利用CSS、JavaScript及Ajax实现图片预加载的三大方法(转)
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- Javascript图片预加载详解 分类: JavaScript HTML+CSS 2015-05-29 11:01 768人阅读 评论(0) 收藏
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- 利用CSS、JavaScript及Ajax实现图片预加载的三大方法及优缺点分析
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- webpack快速入门——CSS文件打包
1.在src下新建css文件,在css文件下新建index.css文件,输入以下代码 body{ background:pink; color:yellowgreen; } 2.css建立好后,需要引 ...
- 动态加载/删除css文件以及图片预加载
动态加载/删除css文件以及图片预加载 功能模块页面 最近,工作中遇到了一个比较奇葩的需求:要在一个页面(PC端)增加一个功能模块,但是这个页面在不久之后要重构,为了新增加的模块可以继续复用, ...
- 从输入 URL 到页面加载完成的过程中都发生了什么
从输入 URL 到页面加载完成的过程中都发生了什么 过程描述 浏览器查找域名对应的 IP 地址: 浏览器根据 IP 地址与服务器建立 socket 连接: 浏览器与服务器通信: 浏览器请求,服务器处理 ...
随机推荐
- 【tf.keras】实现 F1 score、precision、recall 等 metric
tf.keras.metric 里面竟然没有实现 F1 score.recall.precision 等指标,一开始觉得真不可思议.但这是有原因的,这些指标在 batch-wise 上计算都没有意义, ...
- MySQL 库、表、记录、相关操作(3)
MySQL 库.表.记录.相关操作(3) 单表查询 """ 增: insert [into] [数据库名.]表名[(字段1[, ..., 字段n])] values (数 ...
- c语言作业07
问题 答案 这个作业属于那个课程 C语言程序设计II 这个作业要求在哪里 https://edu.cnblogs.com/campus/zswxy/CST2019-2/homework/8655 我在 ...
- Git的安装和使用教程详解
---恢复内容开始--- 本篇笔记聊聊Git的安装和使用教程 一.认 识 Git ...
- 【nodejs原理&源码赏析(7)】【译】Node.js中的事件循环,定时器和process.nextTick
目录 Event Loop 是什么? Event Loop 基本解释 事件循环阶段概览 事件循环细节 timers pending callbacks poll阶段 check close callb ...
- 工作流Activity组件值数据传递获取问题
如图:先简单说一下大致过程 通过具体的菜单节点,加载具体的指令组件.本着低耦合的原件,需要将核查组件从指令组件重拆分出来,作为单独的组件根据业务需要拖拽到指令组件中.但是具体业务方面核查组件一方面需要 ...
- shell 脚本运行 hive sql
#!/b START=$(date +%s); datebegin=`date -d "$1" "+%Y%m%d"` dateend=`date -d &quo ...
- JS中的运算符_函数学习
js中的运算符: 算数运算符: + - * / % ++ -- 逻辑运算符: & | ! && || < > <= ...
- [TimLinux] myblog 首页创建
1. 设计 2. 结构 3. 实现 templates/common/layout.html: <!DOCTYPE html> <html lang="zh"&g ...
- 使用flink实现一个topN的程序
topN功能是一个非常常见的功能,比如查看最近几分钟的阅读最高数,购买最高数. flink实现topN的功能也非常方便,下面就开始构建一个flink topN的程序. 还是像上篇博客一样,从kafka ...