Search code examples
npmwebpackhtml-webpack-plugin

Hot reloading templateParameters for HtmlWebpackPlugin


I have in my webpack.config.js:

const data = require('./src/data.json');

...

new HtmlWebpackPlugin({
    template: "src/index.hbs",
    filename: "index.html",
    templateParameters: {
        data: data
    },
}),

...

module: {
    rules: [
        {
            test:    /\.hbs$/,
            loader:  "handlebars-loader"
        }
    ],
},

devServer: {
    static:     './dist',
    hot:        true,
    liveReload: true,
    open:       false,
    watchFiles: ['src/**/*.hbs', './src/data.json'],

},

When run with npm start hot reloading works for my JS-Modules, but not if i make changes to the data.json. How can i reload the dev server when i make changes to that JSON-File?


Solution

  • You can try to use modern powerful html-bundler-webpack-plugin instead of html-webpack-plugin.

    Use the data plugin option as a JSON or JS filename to recompile and reload pages after changes of variables in the data file without restarting Webpack.

    Using the Bundler Plugin

    • An entry point is a template (HTML, handlebars, EJS, etc.).
    • All your source asset files (scripts, styles, images, etc.) can be specified directly in the HTML template.
    • The plugin resolves source files of assets in templates and replaces them with correct output URLs in the generated HTML.
    • The resolved assets will be processed via Webpack plugins/loaders and placed into the output directory.

    Just one HtmlBundlerPlugin replaces the functionality of many plugins and loaders such as:

    • html-webpack-plugin
    • handlebars-webpack-plugin
    • handlebars-loader
    • mini-css-extract-plugin
    • style-loader
    • and many others

    For example there is your page template ./src/index.hbs:

    <!DOCTYPE html>
    <html>
    <head>
      <!-- `title` is the vaiable passed from data.json via webpack -->
      <title>{{ title }}</title>
      
      <!-- relative path to favicon source file -->
      <link href="./favicon.ico" rel="icon" />
      
      <!-- relative path to SCSS source file -->
      <link href="./style.scss" rel="stylesheet" />
      
      <!-- relative path to JS source file -->
      <script src="./main.js" defer="defer"></script>
    </head>
    <body>
      <h1>Hello World!</h1>
      
      <!-- relative path to image source file -->
      <img src="./images/picture.png" />
    </body>
    </html>
    

    The data file can be a JSON or JS file, e.g. src/data.json

    {
      "title":  "My Title"
    }
    

    The Webpack config example:

    const path = require('path');
    const HtmlBundlerPlugin = require('html-bundler-webpack-plugin');
    
    module.exports = {
      plugins: [
        new HtmlBundlerPlugin({
          entry: [
            {
              import: 'src/index.hbs',
              filename: 'index.html',
              data: 'src/data.json', // <= relative path to data used in this page
            },
            // add your pages here
          ],
          data: 'src/data.json', // <= relative path to global data passed into all pages
          preprocessor: 'handlebars', // <= enable support *.hbs templates
          preprocessorOptions: {
            partials: [
               'src/partials/', // path to your partials
            ],
          },
        }),
      ],
      
      module: {
        rules: [
          {
            test: /\.(css|sass|scss)$/,
            use: ['css-loader', 'sass-loader'],
          },
          {
            test: /\.(ico|png|jp?g|webp|svg)$/,
            type: 'asset/resource',
            generator: {
              filename: 'img/[name].[hash:8][ext][query]',
            },
          },
        ],
      },
      
      // enable live reload
      devServer: {
        static: path.join(__dirname, 'dist'),
        watchFiles: {
          paths: ['src/**/*.*'],
          options: {
            usePolling: true,
          },
        },
      },
    };
    

    Here is the handlebars example used JSON data files as external data passed into templates.

    P.S. You can create a small repository on GitHub and then I can help you do your project working.