Why is webpack not running all plugins when a file change is detected?

Viewed 399

I'm using webpack with watch=true to compile handlebars files into HTML files in a /dist folder.

The HandlebarsWebpackPlugin runs when .hbs files are modified, but I also want it to run when JSON files are modified. The JSON files contain data that is passed to the handlebars templates when they are compiled into HTML.

I added a plugin called webpack-watch-files-plugin thinking that it would watch the JSON files and re-run the whole build when a change is detected, but it doesn't.

Can somebody please explain how does webpack work in this regard? How can I make all the plugins re-run (or at least the handlebars to HTML compilation) when I change a JSON file?

webpack.config.js

const webpack = require('webpack');
const glob = require("glob");
const path = require("path");
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HandlebarsPlugin = require("handlebars-webpack-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
const ImageminPlugin = require("imagemin-webpack-plugin").default;
const WatchFilesPlugin = require('webpack-watch-files-plugin').default;
const mergeJSON = require("./src/utils/mergeJSON");
const handlebarsHelpers = require("handlebars-helpers");

const lang = process.env.npm_config_lang; // lang variable passed as argument to script

const webpackConfig = {
  watch: true,
  watchOptions: {
    ignored: ['node_modules/**', 'dist']
  },
  entry: path.join(__dirname, 'src'),
  plugins: [
    new CleanWebpackPlugin(),

    new HandlebarsPlugin({
      // path to hbs entry file(s). Also supports nested directories if write path.join(process.cwd(), "app", "src", "**", "*.hbs"),
      entry: path.join(__dirname, "src", "emails", "**/*.hbs"),

      // output path and filename(s). This should lie within the webpacks output-folder
      // if ommited, the input filepath stripped of its extension will be used
      output: path.join(__dirname, "dist", "[path]", "[name].html"),
      // you can also add a [path] variable, which will emit the files with their relative path, like
      // output: path.join(process.cwd(), "build", [path], "[name].html"),

      // data passed to main hbs template: `main-template(data)`
      data: mergeJSON(path.join(__dirname, 'src/emails/**/*.json')),

      // globbed path to partials, where folder/filename is unique
      partials: [
        path.join(__dirname, "src", "partials", "*.hbs")
      ],

      // register custom helpers. May be either a function or a glob-pattern
      helpers: {
        projectHelpers: handlebarsHelpers()
      },

      // hooks
      // getTargetFilepath: function (filepath, outputTemplate) {},
      // getPartialId: function (filePath) {}
      onBeforeSetup: function (Handlebars) {},
      onBeforeAddPartials: function (Handlebars, partialsMap) {},
      onBeforeCompile: function (Handlebars, templateContent) {},
      onBeforeRender: function (Handlebars, data, filePath) {
        const mergedData = mergeJSON(path.join(__dirname, 'src/emails/**/*.json'));

        const filePathArray = filePath.split('/');
        const fileName = filePathArray[filePathArray.length-1].split('.hbs')[0];

        if(mergedData[fileName]) {
          // only json specific to this file and language will be used as data for this file
          return {...mergedData[fileName].config, ...mergedData[fileName][lang]};
        } else if(!lang) {
          const errorText = `The language code is required to build the emails. Pass it as an argument with this format "--lang=en-US".`;
          console.log('\n', '\x1b[41m\x1b[37m', errorText, '\x1b[0m');
          throw new Error(errorText);
        }
      },
      onBeforeSave: function (Handlebars, resultHtml, filename) {},
      onDone: function (Handlebars, filename) {}
    }),

    new CopyWebpackPlugin([{
      from: path.join(__dirname, "src/emails/**/imgs/*"),
      to: "[1]/[2].[ext]", // [1] and [2] are groups matched by the regex below
      test: /emails\/([^/]+)\/(.+)\.(jpe?g|png|gif|svg|)$/,
    }]),

    new ImageminPlugin({test: /\.(jpe?g|png|gif|svg)$/i}),

    new WatchFilesPlugin({
      files: [
        path.join(__dirname, "src", "emails", "**/data/*.json")
      ],
      verbose: true
    })
  ]
};

module.exports = webpackConfig;
0 Answers
Related