webpack-5html-webpack-plugin

Webpack does not preserve the directory structure of output HTML files


First, I'm migrating a project from gulp and from the Foundation for Sites SCSS framework to webpack and a different SCSS framework. The project makes a site for a text-heavy law school casebook.

I am very new to Webpack (that's the real problem, I'm sure ;-).

Here's the relevant structure of src:

/src
    /views
        /layouts
        /partials
        /pages
            /teaching
                4 interior HTML files
            index.html
            2 other top-level HTML files
      

(By the way, my entry point is /src/assets/js/app.ts, which in addition to the app's logic also @imports /src/assets/scss/app.scss. All that seems to generate fine.)

The HTML is made this way:

And then:

plugins {
    ...htmlPages
}

In dist I expect to see:

/dist
    /teaching
        4 HTML files
     index.html
     2 other HTML files

Instead I see seven perfectly fine HTML files -- but not in a directory structure.

I would guess that the array of htmlPages plugins present a bunch of files to the rules, which do their thing before the HtmlWebpackPlugins create a file for each. If I break the rule's regex, the generated HTML is just the page content without the template applied. And of note, if I add exclude: /src\/views\/pages\/.*\.html$/ to the rule, I also see the content without the template applied. This experiment tells me the process has each file's full path along the full data flow path.

So who's deciding not to repeat the original directory structure?

Thank you for reading this far.


Solution

  • You can use the html-bundler-webpack-plugin. This plugin simplify Webpack config and provide supporting Nunjucks templates out of the box.

    Using this plugin, you can define the entry as a path to recursively detect all templates from that directory. The output files will have the same folder structure as source template directory.

    Webpack plugin config:

    new HtmlBundlerPlugin({
      entry: 'src/views/pages/', // path to pages
      preprocessor: 'nunjucks', // use Nunjucks templating engine
      preprocessorOptions: {
        // an array of relative or absolute search paths
        views: [
          'src/views/layouts',
          'src/views/partials',
        ],
      },
      data: {
        // pass here the variables available in all templates
        PRODUCTION: PRODUCTION
      }
    });
    

    Note: no additional Webpack loader configuration for html required. The html-bundler-webpack-plugin replaces the functionality of html-loader, nunjucks-html-loader and many other plugins and loaders.

    P.S. you can create a repo on GitHub and I can help you to configure Webpack for your project.