vikdotdev
vikdotdev

Reputation: 105

Generating HTML with relative path to assets using Webpack

I have the following src folder structure:

/src
+-- /app
|   +-- index.js
|   +-- /templates
|       +-- index.html
|       +-- /subfolder
|           +-- nested.html
|
+-- /images
|   +-- webpack.png
| 
+-- /styles
|   +-- index.scss

I am trying to configure webpack to emit multiple html files using templates from app folder. The final build folder structure should look something like this:

/build
+-- /images
|   +-- webpack.png
|
+-- /subfolder
|   +-- nested.html
|
+-- index.html
+-- bundle.js
+-- styles.css

The problem is that after building, index.html and nested.html have the same path to the image <img src="img/webpack.png"> which is incorrect for nested.html

nested.html should have the following path - <img src="../img/webpack.png">.

How can I make webpack set correct path to assets for nested html files ?


Steps to reproduce.

  1. Download the repo
  2. Install packages npm install
  3. Run npm run build

my webpack.config.js

my package.json

According to this thread it is not a problem with html-loader - https://github.com/webpack-contrib/file-loader/issues/272

Webpack docs mention assets sharing between components but provides no examples - https://webpack.js.org/guides/asset-management/#global-assets

html-loader options may have a solution to this but docs doesn't make much sense to me and I can't figure it out - https://webpack.js.org/guides/asset-management/#global-assets

Article I was following to generate htmlWebpackPlugin dynamically - https://extri.co/2017/07/11/generating-multiple-html-pages-with-htmlwebpackplugin/

Upvotes: 3

Views: 2622

Answers (1)

Frank-
Frank-

Reputation: 76

I have had another look this morning and I have a way of doing what you wan't, although it isn't perfect.

If you move your images folder in to your templates folder and update your urls in HTML+SCSS to match.

Change the file-loader settings for images so that it puts them in a directory with the same name as your source directory.

  ...
  {
    loader: "file-loader",
    options: {
      name: "[name].[ext]",
      // outputPath: "img/" 
      // Use same name as source
      outputPath: "images/" 
    }
  }
  ...

Add a test to the walk function so that it only includes html files from the template directory, so that we don't get errors trying to process images with HtmlWebpackPlugin.

  ...
  if (isDirectory) {
        // File is a directory
        ... code ...
      } else if (/\.html$/.test(file)) {
        ... code ...
      }
  ...

And remove html-loader as it was rewriting the image urls, breaking their relative paths.

With these changes Webpack will keep the relative urls in your img tags. It will also create the right structure for that to work in your build directory. The images will work in CSS too, the whole time that is loaded from your build/root directory too.

This isn't a perfect solution, it would be nice for it all to work automagically like a lot of other stuff in Webpack does. But it should accomplish what you want for now, at least until you figure out a better way.

Upvotes: 0

Related Questions