jantimon/html-webpack-plugin

Watch mode memory leak when saving HTML template

helloitsjoe opened this issue · 1 comments

Current behaviour 💣

Summary

Changes to the HTML template in watch mode cause memory to grow and never be garbage collected. I can see htmlWebpackPluginHooksMap (WeakMap cache) grow by an entry every time I save the HTML template file.

Details

Hi folks, this was previously discussed here: webpack/webpack#13127 (comment). It was identified as just a large cache, but it looks like a leak. I have a simple reproduction linked below, more details there but here's the overview:

In HtmlWebpackPlugin, htmlWebpackPluginHooksMap (WeakMap) adds a compilation every time the template HTML file index.template.html is modified. These WeakMap entries are never garbage collected, but I haven't been able to determine why. My one lead is that moduleGraphForModuleMap (WeakMap in Webpack) keys are holding onto references to the Compilation objects. I can see a few other WeakMaps in Webpack growing, but the ModuleMap WeakMap is the only connection I've made between HtmlWebpackPlugin and Webpack holding onto memory.

In the simple reproduction repo memory grows by ~2mb per recompilation, but I'm working in a larger app where the problem is more pronounced. I'm happy to help out here if I can.

Here are some relevant screenshots, also in the readme:

Heap snapshot

Heap snapshot

We can see that each key in that WeakMap has a reference to the compilation, which has a reference to the HtmlWebpackPlugin compiler:

WeakMap

WeakMap

Expected behaviour ☀️

Memory should be stable when making changes to the index.html template in watch mode

Reproduction Example 👾

https://github.com/helloitsjoe/webpack-memory-leak

Environment 🖥

Node.js v20.5.1
darwin 22.5.0
npm 9.8.0
webpack@5.89.0
html-webpack-plugin@5.5.3

After more investigation I believe this is due to Webpack not completely cleaning up after child compilers, and not specific to HtmlWebpackPlugin, see webpack/webpack#17851