CSS url()路径始终相对于CSS文件所在目录,如css/app.css引用同级assets/img/logo.png需写url('../assets/img/logo.png');少一个../即404,因css-loader默认以CSS文件为基准解析,与HTML、JS无关。

CSS url() 路径始终相对于 CSS 文件位置,不是 HTML,也不是 JS 调用处
这是所有路径错乱的根源。比如 CSS 在 css/app.css,图片在 assets/img/logo.png(与 css/ 同级),那必须写 url('../assets/img/logo.png')。少一个 ../ 就 404。开发时可能碰巧对,是因为 dev server 的路径映射有“宽容性”;但打包后路径被真实重写,错误立刻暴露。
Webpack 中 CSS 和 JS 对路径的处理逻辑完全不同
JS 里 import 或 require 图片,路径是相对于当前 JS 文件的;而 CSS 里的 url() 是由 css-loader 解析的,它默认以 CSS 文件所在目录为基准——这个行为无法靠 JS 逻辑绕过。
-
css-loader默认会解析并重写url()中的相对路径,目标是生成最终输出路径 - 如果没配
publicPath,它会按 Webpack output 的publicPath做拼接,常导致多一层或少一层../ - 例如:CSS 文件被打包进
dist/css/app.[hash].css,图片进了dist/static/img/logo.[hash].png,但 loader 默认生成的是url(/static/img/logo.[hash].png),而实际需要的是url(../../static/img/logo.[hash].png)
url-loader 和 file-loader 的 publicPath 必须显式设置
很多人只改了 Webpack 的 output.publicPath 或 Vue CLI 的 assetsPublicPath,却漏掉 loader 层的 publicPath。这两个不是一回事:前者控制 JS/CSS 文件本身的引用路径,后者才真正决定 CSS 里 url() 最终怎么拼。
立即学习“前端免费学习笔记(深入)”;
- 在
url-loader或file-loader的options里加publicPath: '../../'(值取决于你 CSS 输出目录和图片输出目录的相对关系) - 若用
css-loader5+,它的url选项默认为true,且不接受publicPath;此时必须靠url-loader层统一控制 - Vue CLI 2 用户需改
build/utils.js里ExtractTextPlugin.extract()的publicPath参数;Vue CLI 3+ 则应在vue.config.js的css.loaderOptions.css或chainWebpack中配置
用 background 简写会悄悄覆盖 background-image
这个坑和打包无关,但会让调试更混乱:写 background: #fff; 看似只是设背景色,但它等价于 background: #fff none repeat scroll 0% 0% / auto;,其中 none 会把之前声明的 background-image: url(...) 给清掉。
- 要么全程用简写:
background: url('../img/bg.png') no-repeat center/cover; - 要么彻底拆开:
background-color、background-image、background-size各自独立声明 - 检查 Chrome DevTools Elements 面板,如果
background-image值带删除线,说明被更高优先级规则覆盖了,不是路径问题
最易被忽略的是:loader 的 publicPath 和 Webpack output.publicPath 必须协同,且值要根据最终生成的文件目录结构反推——不能凭感觉写 ./ 或 /,得打开 dist 目录,数清楚 CSS 文件到图片文件之间到底隔了几层目录。


















