Webpack 中的相对 CSS url

Posted

技术标签:

【中文标题】Webpack 中的相对 CSS url【英文标题】:Relative CSS urls in Webpack 【发布时间】:2018-01-17 18:18:47 【问题描述】:

Webpack + file-loader + sass-loader 在解析 CSS 背景图像的相对路径时遇到问题。

编译后的 SCSS 文件包含一个相对于 /dist/ 而不是相对于 SCSS/CSS 文档的背景图像的路径。我研究了这个问题; sass-loader 建议使用 resolve-url-loader(带有源映射)。但是,添加 resolve-url-loader 对编译后的 CSS 没有任何影响。

我已经能够通过在文件加载器上将“publicPath”设置为“../..”来解决此问题。或者通过禁用 css-loader 上的“url”设置。两者都不是一个好的解决方案,并且会导致通过 html 或其他来源复制文件和引用图像时出现问题。

Webpack 和 CSS 的在线示例将 CSS 和图像放在同一个文件夹中(通常在根目录中)。这不是我的 webpack 实现的最佳选择。在子文件夹中结构化文件的概念似乎是一个相当基本的要求。这只是错误的方法吗?

运行 Webpack ^3.5.1。 Sass 加载器 ^6.0.6。文件加载器 ^0.11.2。 CSS 加载器 ^0.28.4.

文件结构

example/
├── dist/
│   ├── assets
│   │   ├── media
│   │   │   └── logo.png
│   │   └── styles
│   │       ├── app.css
│   │       └── app.css.map
│   ├── index.html
│   └── app.bundle.js
└── src/
    ├── assets
    │   ├── media
    │   │   └── logo.png
    │   └── styles
    │       └── app.scss
    └── app.js

app.scss

body 
  background: url(../media/logo.png);

app.css

body 
  background: url(assets/media/logo.png); //This should be ../media/logo.png

app.js

require('./assets/styles/app.scss');

webpack.config.js

const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = 
  entry: './src/app.js',
  output: 
    path: path.resolve(__dirname, 'dist'),
    filename: 'app.bundle.js'
  ,
  devtool: 'source-map',
  module: 
    loaders: [
      
        test: /\.scss$/,
        use: ExtractTextPlugin.extract(
          use: [
            
              loader: 'css-loader',
              options: 
                sourceMap: true
              
            , 
              loader: 'resolve-url-loader'
            , 
              loader: 'sass-loader',
              options: 
                sourceMap: true
              
            
          ]
        )
      , 
        test: /\.png$/,
        use: [
          
            loader: 'file-loader',
            options: 
              name: 'assets/media/[name].[ext]'
            
          
        ]
      
    ]
  ,
  plugins: [
    new ExtractTextPlugin(
      filename: 'assets/styles/app.css'
    )
  ]

【问题讨论】:

【参考方案1】:

ExtractTextPlugin 有一个publicPath 选项可以解决此问题。


  test: /\.scss$/,
  include: [
    path.resolve(__dirname, "src/assets/styles")
  ],
  use: ExtractTextPlugin.extract(
    publicPath: '../../',
    use: [
      
        loader: 'css-loader',
        options: 
          sourceMap: true
        
      , 
        loader: 'sass-loader',
        options: 
          sourceMap: true
        
      
    ]
  )

include 数组添加到特定目录中的目标文件。推荐用于所有样式表都位于同一文件夹中的情况。

【讨论】:

就我而言,publicPath: './' 致力于解析相对于输出目录的文件路径资产。【参考方案2】:

url(...) 中的路径不正确的原因是 webpack 生成的路径相对于输出目录,而不是输出的 css 文件。

你可以使用css-url-relative-plugin来解决这个问题,它会通过重新计算输出css和assets文件的关系,将url(...)替换为正确的相对路径。

【讨论】:

以上是关于Webpack 中的相对 CSS url的主要内容,如果未能解决你的问题,请参考以下文章

Webpack @font-face 相对路径问题

Angular 2 AOT Webpack CSS 相对嵌套 url

webpack中的~

Webpack实现将CSS中的px转换为rem

Webpack实现将CSS中的px转换为rem

Webpack style-loader / css-loader: url() 路径解析不起作用