webpacksubdirectoryhtml-webpack-pluginwebpack-file-loaderwebpack-html-loader

Webpack File-loader returns wrong path to subfolder


I'm making a website with multiple entry points. With the following structure.

I'm using file-loader to load the images on the js files. Here's my webpack config:

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: {
    index: './src/index.js',
    products: './src/pages/products/products.js',
  },
  output: {
    filename: '[name].[hash:20].js',
    path: path.resolve(__dirname, "../dist")
  },

  module: {
    rules: [
      {
        test: /\.(woff|woff2|ttf)$/,
        use: ['url-loader']
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        loader: 'file-loader',
        options: {
          outputPath: 'assets'
        }
      },
      {
        test: /.(css|scss)$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: 'postcss-loader',
            options: {
              plugins: function () {
                return [
                  require('autoprefixer')
                ];
              }
            }
          },
          "sass-loader"]
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "../src/index.html"),
      inject: true,
      chunks: ['index'],
      filename: 'index.html'
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "../src/pages/products/products.html"),
      inject: true,
      chunks: ['products'],
      filename: 'products/index.html'
    }),
    new HtmlWebpackPlugin({
      template: path.join(__dirname, "../src/pages/product/product1/product1.html"),
      inject: true,
      chunks: ['product1'],
      filename: 'products/product1/index.html'
    }),
    new MiniCssExtractPlugin({
      filename: "[name].[contenthash].css",
      chunkFilename: "chunk-styles.css"
    }),
  ]
};

All assets are built into dist/assets and I access them by importing them in the js. The resulting url in the index.html for a given image is assets/[image-hash]

The problem is that the html in any subfolder finds anything because it's looking inside their subfolder level. The url for them to work should instead be ../assets/[image-hash] and ../../assets/[image-hash] for a deeper level.

How can I either modify the generated URL to always look in the root folder or build the required images inside each subfolder I have?

I also tried using html-loader (which I think is a better solution) to avoid setting image src through js but ran into the very same problem.


Solution

  • You HTML links are relative to the html file. If you add a / in front of the urls like assets/image.jpg , it will be relative to the root of your project. E.g. https://localhost:3000/assets/image.jpg, or https://www.mypage.com/assets/image.jpg and it should work fine.