Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

生成的css文件中background url()图片路径问题 #481

Closed
challengezhou opened this issue Nov 22, 2016 · 48 comments
Closed

生成的css文件中background url()图片路径问题 #481

challengezhou opened this issue Nov 22, 2016 · 48 comments

Comments

@challengezhou
Copy link

challengezhou commented Nov 22, 2016

重现项目在这

使用vue init webpack创建的项目,改了三个地方

  1. webpack.base.conf.js配置文件output的publicPath注释起来
  2. App.vue中给body加了background样式
  3. 把url-loader的limit改成了6000,避免base64转换而不使用file-loader

现象:

npm run dev没问题 因为跟build的目录不同
当npm run build后
提取出来的css文件中url()中图片的路径是static/img/logo.82b9c7a.png这样的,应该是根据url-loader来的,但这个路径是相对于css文件的,所以造成找不到这张图片

个人几个解决方案:

  1. 把webpack配置文件的output的publicPath设置成’/‘(初始化的项目默认是这样的),这样所有引用文件都会从’/‘开始,不会出现找不到文件的情况。但我是在一个域名下有多个项目的,不一定会把这个项目放到根目录。如:a.com/test1/index.html 会放到test1目录下,如果设置成’/‘就会直接到a.com/下找,还是会找不到,如果修改成/test1 因为这个目录非常多,更新特别频繁,如果每一个都需要修改也挺麻烦,上边的修改把output的publicPath注释起来也是因为这个
  2. webpack.prod.conf.js中ExtractTextPlugin插件目录中的css文件夹搞成上级目录“..”,这样css文件就会跟index.html在相同目录,其中的url目录就会正确了,但感觉破坏了目录结构,不知道好不好~(现在用的这种解决方案,因为多个项目可以使用相同的配置)
  3. 手动改~因为这几次样式里边url()用的还比较少,多了就不靠谱了

这个问题纠结了很久 看了css-loader file-loader文档,看了很多以前的issue,网上查了很久,都没有找到相应的解决方法,因为实在找不到应该修改哪一部分。上边说的几个解决方法,总感觉不靠谱~
忍不了了所以来提个issue 望大牛们指点迷津

@xiaoosnggao
Copy link

同求问

@cristicVictory
Copy link

我也有引用图片出了问题

@githoniel
Copy link

same to me
it seems option.publicPath of ExtractTextPlugin is broken here

return ExtractTextPlugin.extract('vue-style-loader', sourceLoader,{
	publicPath: "../../../../"
})

just work the same as publicPath: "../" and publicPath: "/"

if set to publicPath: "./../", webpack error with any .vue

Module not found: Error: Cannot resolve 'file' or 'directory' ./../../../../node_modules/extract-text-webpack-plugin/"} 

@xmflswood
Copy link

mark

@Krispomoho
Copy link

同问,主要问题出在background-image的引用里,每次都要先把图片import 进来

@Ivorzk
Copy link

Ivorzk commented Mar 21, 2017

同问

@Ivorzk
Copy link

Ivorzk commented Mar 21, 2017

这个问题 很严重的 因为我们做汽车网站的 有些时候背景图会用到很多!

@xiaoyang110
Copy link

将真,我也遇到这种问题 ,找了好几天这个问题,最后不得已把这个图片转换成了base64。。。

@pangao66
Copy link

同问,目前采用手动的方式处理了,没有转化成base64的大图片,路径都会相对css的static,所以错误.只能在打包后生成的app.css里面全部替换,将./static替换成../static,这样暴力解决的,但......

@xiaoyang110
Copy link

我的解决了,路径改为绝对路径就没问题了

@githoniel
Copy link

这问题还在讨论啊,根据dev/build,给file-loader设置不同的publicPath可以解决dev build时路径不同的问题

但是JS和CSS中图片路径,分别是根据所被引用的CSS或者JS的路径来计算相对路径。如果两者层次不同,就无法用../多次的方式回到相同的某路径来统一路径。这个问题我也没找到方法,但是直接规避就好了

@lzqGiser
Copy link

关注一下你的.vue文件,相对于这个来。就可以的

@wukongtime
Copy link

mark

@liwenlong
Copy link

mark,也遇到这个问题了,第三方组件里面的css引用img图片了,路径就不对了

@pspgbhu
Copy link

pspgbhu commented Jun 5, 2017

对于楼主的问题,主要是需要单独为 css 配置 publicPath 。
ExtractTextWebpackPlugin 提供了一个 options.publicPath 的 api,可以为css单独配置 publicPath 。

对于用 vue-cli 生成的项目,dist 目录结构如下:

dist
├── index.html
└── static
    ├── css
    ├── img
    └── js

经常遇见的问题是 css 中 background-image 的相对路径不能正确的引用到 img 文件夹中。但是用 ExtractTextWebpackPlugin 的 publicPath 配置就可以。

更改 build/utils.js 文件中 ExtractTextPlugin 插件的options 配置:

    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        publicPath: '../../',         // 注意配置这一部分,根据目录结构自由调整
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }

最后附上 extract-text-webpack-plugin 的文档。
https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/master/README.md

@flyher
Copy link

flyher commented Jun 6, 2017

@WongYuYe
Copy link

WongYuYe commented Jun 7, 2017

刚看到的方法的,很有用
https://wongyuye.github.io/2017/06/07/vue-%E6%89%93%E5%8C%85%E8%83%8C%E6%99%AF%E8%B7%AF%E5%BE%84%E9%97%AE%E9%A2%98/

@xcsweb
Copy link

xcsweb commented Aug 17, 2017

如果说由后端php分配域名,而我的页面static不放在根目录如何解决,也就不能使用绝对路径了

@helloworld3q3q
Copy link

@pspgbhu 这个办法太好了!!!!!!!!!!!!!!!!!!!!!!!!!!!!

@CodeDreamfy
Copy link

@pspgbhu 解决了,感谢!

@unclexiao
Copy link

@pspgbhu 非常赞,终于找到完美解决方案啦!

@challengezhou
Copy link
Author

challengezhou commented Oct 11, 2017

更改下问题样式,改好看点~

@xiaoqf96
Copy link

mark

@xiaolong2013
Copy link

@pspgbhu 确实能解决问题 mark

@maggiew61
Copy link

@pspgbhu 你的方法成功! 感謝大神

@meishadevs
Copy link

@pspgbhu 问题解决了,谢谢大佬

@Hellowor1d
Copy link

@pspgbhu O(∩_∩)O 谢谢,找了一晚上的解决方案,这个最简单有效了!!!

@lndj
Copy link

lndj commented Dec 23, 2017

@pspgbhu Thanks.

@zigang93
Copy link

zigang93 commented Jan 9, 2018

{
                test: /\.scss$/,
                use: extractSass.extract({
                   
                    use: [
                        {
                            loader: "css-loader",
                            options: {
                                minimize: true,
                            }
                        },
                        {
                            loader: "resolve-url-loader"
                        },
                        {
                            loader: "sass-loader",
                            options: {
                                sourceMap: true
                            }
                        }
                    ],                 
                    fallback: "style-loader",
                    publicPath: "../"
                    
                })
},

还是无法解决!

@pspgbhu
Copy link

pspgbhu commented Jan 10, 2018

@zigang93

更改 build/utils.js 文件中 ExtractTextPlugin 插件的options 配置:

    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        publicPath: '../../',         // 注意配置这一部分,根据目录结构自由调整
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }

@tzq582905
Copy link

@pspgbhu 赞一个,完美

@zigang93
Copy link

zigang93 commented Feb 13, 2018

@pspgbhu
更改 build/utils.js
这句我有点不肯定 是在node_module??
我根本没有用vue-loader.. 我是看到很多issue 引导我来这里

问题出于我的file-loader 的 publicPath ,
终于解决了我的疑问和问题了

@Topppy
Copy link

Topppy commented Feb 27, 2018

我的问题通过干掉postcss的postcss-url插件解决了

@laozhujia
Copy link

其实我也没理解题主的意思,是不是想一次build 在不同的publicPath环境中运行,通过css 的相对路径加载图片。感觉这样确实有难度。因为,所有的图片都是放到imgs直接目录下ExtractTextPlugin稍微改下就可以实现,但如果imgs里面再分gif,png,jpg文件夹,相对路径就更复杂了,需要ExtractTextPlugin去读取你的css提取目录配置,不同图片的 url-loader(file-loader)目录规则,才能决定如何替换。
如果是绝对路径的,设置publicPath就可了,如果是test1下面就设置成 ‘/test1/’
vue 项目中发现的一个事情是,如果css 引用的是绝对定位的static下的图片,貌似不经过url-loader处理的,直接复制static下的图片到dist下的static下面引用。

@vok123
Copy link

vok123 commented May 7, 2018

我们似乎忘记了有这么一个标签 <base href="资源路径" />
http://www.w3school.com.cn/html5/tag_base.asp

@wakefun
Copy link

wakefun commented Aug 14, 2018

@laozhujia 在.vue单文件组件中写样式,背景图片url使用绝对路径可以避免使用相对路径层级过深的问题,但是打包后依旧是绝对路径,如果项目不是跑在根目录下就会出现问题;请问有什么好的解决办法嘛,求教

@laozhujia
Copy link

laozhujia commented Aug 14, 2018

@badaoshen 假设你项目放在test目录下,如果目录和工程一致,直接设置publicPath=‘/test/' ,打包后会在所有引用前加上这个publicPath的路径, vue-cli2.0配置webpack.base.conf.js 中output.publicPath, 可以直接修改,也可以保留build.assectsPublicPath 修改config目录下index里build.assetsPublicPath。如果是img css 另外存放目录,可以参考 本页 pspgbhu 的修改ExtractTextPlugin的publicPath 覆盖output的publicPath方法
(引用不是static 目录下的图片,需要使用url-loader加载图片,不然应该没法实现图片引用)
注意vue-cli3.0以后,publicPath 变成了vue.config.js 里的baseUrl 设置如下
baseUrl: process.env.NODE_ENV === 'production' ? '/test/' : '/',
vue-cli3.0 的ExtractTextPlugin设置没研究过,见谅。(3.0配置和2.0有巨大差别,入坑要谨慎)

@wakefun
Copy link

wakefun commented Aug 15, 2018

@laozhujia 查了下webpack关于路径处理的文档,使用绝对路径的时候会被直接忽略,例如:

background-image: url("/static/img/baseBg.png");
//打包后原封不动emmmmmm····

但是在css中使用相对路径会因为项目文件分级出现异常多的"../../../../../",最后的解决方案是使用模块路径,图片放到src/assets/img中,自己配置了一个alias:

//在webpack.base.conf.js中
alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
      'img':resolve('src/assets/img')  //配置一个img的别名指向src/assets/img
    }
//相对应的路径就写成:
background-image: url("~img/baseBg.png");//"~"号代表使用alias
//打包发布的时候参照pspgbhu的方法配置

此方案优点就是路径简洁明了,打包的时候会转为相对路径便于项目发布,缺点就是IDE无法识别,会提示错误 ( 辣鸡webstorm(メ゚Д゚)メ逃~

@todoi
Copy link

todoi commented Sep 3, 2018

@pspgbhu 试了一下, 解决了我的问题, 感谢!

@Yanhongliang100
Copy link

对于楼主的问题,主要是需要单独为 css 配置 publicPath 。
ExtractTextWebpackPlugin 提供了一个 options.publicPath 的 api,可以为css单独配置 publicPath 。

对于用 vue-cli 生成的项目,dist 目录结构如下:

dist
├── index.html
└── static
    ├── css
    ├── img
    └── js

经常遇见的问题是 css 中 background-image 的相对路径不能正确的引用到 img 文件夹中。但是用 ExtractTextWebpackPlugin 的 publicPath 配置就可以。

更改 build/utils.js 文件中 ExtractTextPlugin 插件的options 配置:

    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        publicPath: '../../',         // 注意配置这一部分,根据目录结构自由调整
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }

最后附上 extract-text-webpack-plugin 的文档。
https://github.com/webpack-contrib/extract-text-webpack-plugin/blob/master/README.md

请问升级到webpack4怎么解决的这个问题

@StormBlue
Copy link

@Yanhongliang100 可以使用MiniCssExtractPlugin.loader,同样的配置。

@monw3c
Copy link

monw3c commented Mar 12, 2019

@Yanhongliang100 可以使用MiniCssExtractPlugin.loader,同样的配置。

能否贴下代码看看?

@StormBlue
Copy link

StormBlue commented Mar 12, 2019

@Yanhongliang100 可以使用MiniCssExtractPlugin.loader,同样的配置。

能否贴下代码看看?

项目是以 vue-element-admin 为基础构建的,升级到webpack4后,将build/utils.js 中
loaders.push(MiniCssExtractPlugin.loader)
修改为

loaders.push({
    loader: MiniCssExtractPlugin.loader,
        options: {
          // 解决css中backgroud-url资源在编译后的路径问题
          publicPath: '../../'
        }
 })

@i-Gnomo
Copy link

i-Gnomo commented May 9, 2019

@badaoshen 我项目部署在了二级域名下,导致css背景图都显示不出来,配置了url-loader也没生效,看到你的方案才意识到自己写的绝对路径没有被解析,现在已经完美解决了,非常感谢!O(∩_∩)O

@532604872
Copy link

532604872 commented Aug 25, 2021

module: {
    rules: [
      {
        test: /\.less$/i,
        use: [
          devMode ? 'vue-style-loader' :
            {
              loader: MiniCssExtractPlugin.loader,
              options: {
                /*
                 * 复写css文件中资源路径
                 * 因为css文件中的外链是相对与css的,
                 * 我们抽离的css文件在可能会单独放在css文件夹内
                 * 引用其他如img/a.png会寻址错误
                 * 这种情况下所以单独需要配置../,复写其中资源的路径
                 */
                publicPath: '../'
              }
            },
          'css-loader',
          {
            loader: 'less-loader',
            options: {
              lessOptions: {
                javascriptEnabled: true
              }
            }
          }
        ]
      },
   ]
 }

@Skura23
Copy link

Skura23 commented Dec 2, 2021

一言以蔽之, css里使用@这种路径别名的时候要在前面加上~, 否则识别不了,
即css里这样用:
background-image: url(~@/assets/images/0.png);
就可以了

@xielearncode
Copy link

background-image: url("~@/assets/app_images/leadspace.png");

assetssrc 目录下
js中用 @ 代表当前目录,css中使用 ~@ 代表当前目录

@weiChow
Copy link

weiChow commented Jan 25, 2024 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests