webpack-contrib / mini-css-extract-plugin

Lightweight CSS extraction plugin
MIT License
4.67k stars 388 forks source link

Image paths in css files have weird prefixes ..// #966

Closed dclnet closed 2 years ago

dclnet commented 2 years ago

Bug report

webpack v5.74.0 mini-css-extract-plugin v2.6.1

Actual Behavior

Image paths in css files have weird prefixes ..// .img-div { width: 486px; height: 334px; background-image: url(..//img/df352ceb7b196bcd781d.png); }

Expected Behavior

Use the ../ prefix for image paths .img-div { width: 486px; height: 334px; background-image: url(../img/df352ceb7b196bcd781d.png); }

How Do We Reproduce?

I found the key configuration code is this new MiniCssExtractPlugin({ filename: "css/[name]-[contenthash:8].css" }) With this configuration, the generated css file will be placed in the directory css. Need to refer to the image in the img directory at the same level as css, need ../, but it generates ..//

This is a demo that reproduces the bug: webpackDemo2.zip

alexander-akait commented 2 years ago

Please remove publicPath everywhere, webpack automatically creates relative URLs, you have two slashes because publicPath: 'img/', you don't need it, feel free to feedback

dclnet commented 2 years ago

Please remove publicPath everywhere, webpack automatically creates relative URLs, you have two slashes because publicPath: 'img/', you don't need it, feel free to feedback

Yes, it's work, thanks! before modification:

module.exports = {
  ...
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
    publicPath: '',  // <--- 1
    assetModuleFilename: "[hash][ext]",  // <--- 2
  },
  plugins: [
    ...
    new MiniCssExtractPlugin({
      filename: "css/[name].css"
    })
  ],
  module: {
    rules: [
      ...
      {
        test: /\.(png|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
        generator: {
          publicPath: 'img/',  // <--- 3
          outputPath: 'img'    // <--- 4
        }
      },
      {
        test: /\.css$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      }
    ]
  }
}

After modification, it works fine:

module.exports = {
  ...
  output: {
    filename: 'js/[name].js',
    path: path.resolve(__dirname, 'dist'),
    clean: true,
    // publicPath: "/", // <--- remove it or set a publicPath value (don't "")
    // assetModuleFilename: "[hash][ext]", // probably not needed
  },
  plugins: [
    ...
    new MiniCssExtractPlugin({
      filename: "css/[name].css"
    })
  ],
  module: {
    rules: [
      ...
      {
        test: /\.(png|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
        generator: {  // delete all, set a filename
          filename: 'img/[name]-[hash:8][ext]'
        }
      },
      {
        test: /\.css$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
        ]
      }
    ]
  }
}