jantimon / html-webpack-plugin

Simplifies creation of HTML files to serve your webpack bundles
MIT License
10.71k stars 1.31k forks source link

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

Closed robotsmeagol closed 7 months ago

robotsmeagol commented 7 months ago

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.

alexander-akait commented 7 months ago

You should not run:

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

it is bad for perf

alexander-akait commented 7 months ago

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

robotsmeagol commented 7 months ago

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

alexander-akait commented 7 months ago

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

robotsmeagol commented 7 months ago

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

alexander-akait commented 7 months ago

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

robotsmeagol commented 7 months ago

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

alexander-akait commented 7 months ago

What do you mean won't regenerate?

robotsmeagol commented 6 months ago

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

alexander-akait commented 6 months ago

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

alexander-akait commented 6 months ago

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

HcySunYang commented 3 months ago

Hi @alexander-akait , has the issue about the cache been fixed right now? And I have an addition question: if we change the cache to false, doesn't it mean that the HTML file will be regenerated so long as you make changes to your source code no matter what files you are touching, is that right?

alexander-akait commented 3 months ago

Yeah( I am still working on it, anyway HTML generation is fast, so just check it out

HcySunYang commented 3 months ago

The HTML can be generated fast, but it causes the dev server to reload the whole page, HMR won't work in that case, right? So in a large project, the impact is significant

alexander-akait commented 3 months ago

The HTML can be generated fast, but it causes the dev server to reload the whole page, HMR won't work in that case, right? So in a large project, the impact is significant

HTML should be generated only when you make changes in HTML files, but I don't you did it often