jantimon/html-webpack-plugin

how to make webpack recompile on dev mode with cache on?

robotsmeagol opened this issue · 11 comments

trying to write a plugin based on HtmlWebpackPlugin to change the output of html.

dev mode with cache on, if index.html is not changed, how to make webpack recompile and generate html

class MyPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap("MyPlugin", (compilation) => {
      HtmlWebpackPlugin.getCompilationHooks(compilation).beforeEmit.tapAsync(
        "MyPlugin",
        (data, cb) => {
           data.html += Date.now();
           cb(null, data);
        },
      );
    });

    setInterval(() => {
      compiler.compile()
    }, 60000)
  }
}

dev mode with cache on, compiler.compile() won't regenerate html.

You should not run:

setInterval(() => {
      compiler.compile()
    }, 60000)

it is bad for perf

Sorry I don't undestand what do you try to do

i'm trying to get data from server and inject into html, like this

const res = await axios.get('xxx.com/xxxxx')
data.html += res.data

on dev mode, i want to use timer to check whether data from server changed and regenerate html if changed

Please use HtmlWebpackPlugin.getHooks(compilation).beforeEmit right now (getCompilationHooks is not released), I don't recommend to run compiler.compile using times, you can send a HEAD request and check it is 304 code or not, and only when somethings changed re-run compilation

how to re-run compilation, do u mean npm run dev again?

@robotsmeagol to rerun compilation I recommend to make compiler.watching.invalidate(), note compiler.watching is not undefined only when you watch

i tried compiler.watching.invalidate(), but only first time this would works, after that html won't regenerate

What do you mean won't regenerate?

U can check on this demo
in config/Myplugin.js, i inject customData to html
customData is always 100 and never changed

Solution:

const HtmlWebpackPlugin = require("html-webpack-plugin");
const path = require("path");

class MyPlugin {
  constructor() {
    this.pathToData = path.resolve(__dirname, "./my-data.json");
  }

  apply(compiler) {
    compiler.hooks.thisCompilation.tap("MyPlugin", (compilation) => {
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        "MyPlugin",
        (data, cb) => {
            let content;

            try {
                content = compilation.inputFileSystem.readFileSync(this.pathToData, "utf8");
            } catch (error) {
                cb(error);

                return;
            }

            content = JSON.parse(content);

            compilation.fileDependencies.add(this.pathToData);

            data.html = data.html.replace(
                "</head>",
                `<script>window.customData=${JSON.stringify(content.value)}</script></head>`,
            );

            cb(null, data);
        },
      );
    });
  }
}

module.exports = MyPlugin;

File:

my-data.json

{
  "value": "11244123"
}

Add:

{
  watchFiles: [require("path").resolve(__dirname, "my-data.json")],
  // Other options
}

to config/webpackDevServer.config.js

And disable cache for HtmlWebpackPlugin

new HtmlWebpackPlugin(
        Object.assign(
          {},
          {
            cache: false,
            inject: true,
            template: paths.appHtml,
          },
          isEnvProduction
            ? {
                minify: {
                  removeComments: true,
                  collapseWhitespace: true,
                  removeRedundantAttributes: true,
                  useShortDoctype: true,
                  removeEmptyAttributes: true,
                  removeStyleLinkTypeAttributes: true,
                  keepClosingSlash: true,
                  minifyJS: true,
                  minifyCSS: true,
                  minifyURLs: true,
                },
              }
            : undefined,
        ),
      ),

i.e. cache: false, so webpack will automatically reload page and apply new data

There is a bug in cache for html-webpack-plugin, that is why we disable it, I am working on the new major release without this bug, cache will work without extra setup in future and without bugs