webpack: Webpack4 has memory leak in development mode
Do you want to request a feature or report a bug? bug
What is the current behavior?
The memory increased when running webpack4 in development, and the memory didn’t release. So there was memory leak.
Then node will throw error
JavaScript heap out of memory
I saw the heapsnapshot, there was many repeated String Objects which were compiled by webpack.
If the current behavior is a bug, please provide the steps to reproduce.
run webpack development mode with , update the business code and waiting rebuild, then update the code…you will see the increasing memory.
What is the expected behavior? Clear memory in time. If this is a feature request, what is motivation or use case for changing the behavior?
Please mention other relevant information such as the browser version, Node.js version, webpack version, and Operating System. webpack@4.2.0
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 167
- Comments: 156 (35 by maintainers)
Commits related to this issue
- fix memory leak with HMR fixes #6929 — committed to webpack/webpack by sokra 6 years ago
- make the cache a WeakMap to not leak memory fixes #6929 — committed to webpack/webpack by sokra 6 years ago
- Omitting FaviconsWebpackPlugin from dev build since it has known memory leaks with HMR reloads: https://github.com/webpack/webpack/issues/6929#issuecomment-463148786 — committed to folio-org/stripes-core by ryandberger 5 years ago
- Switching favicons-webpack-plugin to newer fork of project webapp-webpack-plugin which addresses dev server memory leak per https://github.com/webpack/webpack/issues/6929#issuecomment-463148786 — committed to folio-org/stripes-core by ryandberger 5 years ago
- docs: maybe fix memory leak [chunkhash] might cause gc problems: https://github.com/webpack/webpack/issues/1914 see also https://github.com/webpack/webpack/issues/6929 — committed to vuetifyjs/vuetify by KaelWD 5 years ago
Got the same issue when developing with hot reload.
Ok this leak is a tricky one. Here is what happens:
From the devtools (when using the memory profiler you can see leaked
Compilation
objects. They are held by this chain:Some
module.exports
has awebpack
property holding the Compilation object. Thewebpack
property is this one:https://github.com/postcss/postcss-loader/blob/928d5c41d5e2bdec130b3c0899760889466ae7bd/lib/index.js#L93
It’s added to the postcss context.
The context should be temporal, but it’s actually
Object.assign
ed to the object returned bycosmiconfig
:https://github.com/michael-ciniawsky/postcss-load-config/blob/348fb5b62fcd01f93cfc768859a82458e093d035/index.js#L59
cosmiconfig
returns themodule.exports
for the.postcssrc.js
file. But why is thisModule
still hold.cosmiconfig
usesrequire-to-string
which does the following to load the file:https://github.com/floatdrop/require-from-string/blob/b81e995c6ff82fbf71d9ee7a9990b10794fecb98/index.js#L24-L29
This doesn’t add the module to the
require.cache
, but it still adding the module as child to the parent module. That’s the leak.Some things could have done better higher in the chain, but they are not the root cause.
Compilation
reference from the loader context once the loader finish compiling. This would decrease the amount of leaked memory a lot.postcss-load-config
could assign the context to a new object likeassign({}, config, ctx)
instead of modifying the object. This would decrease the amount of leaked memory.How to fix it?
It’s actually already fixed in require-to-string version 2 via this commit:
https://github.com/floatdrop/require-from-string/commit/ca2b81f56cc6d5480a25ca8b2be5887de2dfb53c
So cosmiconfig can update it’s dependency, which it already has in version 3 via this commit:
https://github.com/davidtheclark/cosmiconfig/commit/3846b1186376c1133e00ffb576434d05d8eb6a01
They actually stating that this fixes a memory leak in require-to-string.
So
postcss-load-config
has to update its cosmiconfig dependency. cc @michael-ciniawskyNote that cosmiconfig is already at version 5, but this seem to be unusable because of this bug: https://github.com/davidtheclark/cosmiconfig/issues/148. This would break watching the config file.
They are proposing to use https://github.com/sindresorhus/clear-module but this package has the same memory leak bug as
require-to-string
had. cc @sindresorhusSo my proposal is to update cosmiconfig only to
^3.1.0
.Here is a little guide how to find memory leaks in webpack.
process._debugProcess
to attach to a running node process.Objects allocated between Snapshot 1 and Snapshot 2
Compilation
Compilation
group.Compilation
objectsRetainer
list. It’s automatically expanded in the correct way.I just upgraded from 3.10.0 to 4.5.0 and I’m seeing this sporadically in development:
The only change I made to my
config
file was addingmode: 'development'
.Отличное решение. Так держать.
If I keep editing a single file and do a save after edit, webpack increases memory by ~30MB. The project is https://github.com/Microsoft/language-server-protocol-inspector if you are interested.
I’m linking to a dev version of
vue-cli
that’s using webpack 4.15.1:Here is a gif. As you see, all I’m doing is
Мда, то есть тебе не достаточно этих репортов? 90% которых ссылаются на неверно реализованное кеширование дев сервера… И да, это видимо главная проблема, которая до сих пор не исправлена, but issue closed, np,
@CarterLi Can you create minimum reproducible test repo?
@afwn90cj93201nixr2e1re Я настоятельнр рекомендую использовать анлийский для общения. Проблемы с переполнением памяти dev сервера известна при долгой работе и открыта в репозитории dev сервера, нет никакого смысла в дубликате и ее не возможно исправить на стороне webpack. Репортов недостаточно? Половина из них просто спам без какой-либо информации, я не могу починить что-то где-то не зная в чем проблема, извините я не джин или маг. Остальная половина или уже не актулально и устарело, или в сторонних плагинах, который мы тоже не можем исправить. Хочешь быстрого решения - создай хорошо описанную проблему с примером, хочешь еще быстрее - помоги в решении, это открое программное обеспечение.
any progress on this one?
@evilebottnawi as soon as we opt in into code splitting, we may have a memory leak.
I finally have a small project that launches webpack watch and a “scrambler” (something that edits your entry points for you automatically) side by side => https://github.com/Sinewyk/webpack_leak_6929
By editing the
node --max_old_space_size=X
parameter in the package.json from 50 to 75 we get a OOM in ~15 to ~60 seconds.Install and
yarn test
and you may use something likeGENERATE_HEAP_DUMP=true HEAPDUMP_INTERVAL=5000 yarn test
to see in action the memory leak of the code splitting.Finally I understand why I saw tons of SyncBailHook and stuff in the previous dumps, it’s how all the various Chunks Optimization are registered apparently. And it leaks the compilation objects between runs.
@afwn90cj93201nixr2e1re Нет ничего сложного открыть новую проблему с воспроизводимым примером ошибки/зависания/утечки и тд. Используйте только анлийский язык в будущем.
I found two leaks, both fixed in the PR referenced above.
There is still one known leak, but I can’t do much about it. The in-memory filesystem piles up files when they contain a hash, i. e.
656cd54965df5bcf669a.hot-update.json
…I returned to a git branch after a two week vacation where I then installed the latest versions of Webpack and css-loader only to experience this error. I was able to prevent it by ensuring that I had this in my config:
I had previously been omitting the entire
optimization
property when building for karma.postcss-loader
v2.1.6 🎉I think we can fix this behavior for next major release
Something to note here: If you are using a watch mode or dev-server, webpack opts to using an in-memory file system. This means, that anything generating a deterministic results [hashed file names] will persist in the memory file system forever until watch mode is killed and started again.
We need minimum reproducible repo, without this it makes no sense to write about the fact that you have a problem. Thanks!
I’ll take a look…
I close the issue because there are many different problems and it is not possible to track them, many problems have been fixed, if you encounter a problem please create a new issue with a reproducible test repo, thanks
I did some more investigation on my leak involving
dojo-webpack-plugin
(see the updated test case) and I found the root cause of the leak.Long story short: it is probably not webpack’s fault. The gist of what
dojo-webpack-plugin
is doing is the following.As you can see, it is registering a
Compiler
hook that internally holds a reference to eachCompilation
object. This leaks all compilations via the tapable hook. I also tried the equivalent webpack 3 code and it leaks the same.I will be reporting this to the plugin author since I guess this is not something a plugin should do, isn’t it?
After i’ve commented out
devtool: 'inline-source-map',
it worked without memory exception, obviously also without source maps and normal debugging.After i’ve tried to add TerserPlugin to optimization (or plugins) section, and it fails again, so obvious that there is a problem with source maps library
node_modules\source-map\lib\util.js
(Terser)node_modules\source-map\lib\source-node.js
( devtool: ‘inline-source-map’ )so i stick with inline-cheap-source-map option, at least it makes hot reload possible.
One workaround is to increase node’s memory allocation. You can do this by setting the node flag
--max_old_space_size
when calling node, or setting the default node flags environment variable:project git: https://github.com/zD98/webpack-memory-test
npm start
Because the repo is very small, so multiple operations that change code quickly can increase the memory, and it would not be released.I confirm that "devtool: ‘source-map’ " forces huge memory leak. But it is not the only problem: "devtool: ‘none’ " helps, but memory still leaks slowly.
I’ve tried what @michael-ciniawsky suggested but still getting the error.
Seems like it’s happening at the same place as ElvisKang’s case
Anybody still having this?
submitted this PR: https://github.com/michael-ciniawsky/postcss-load-config/pull/151
Take a look at https://github.com/Sinewyk/webpack_leak_6929 for a practical example on how to quickly generate heapdumps and OOM errors (you need to reduce your use case to what truly breaks it). Copy/paste your config and check it breaks, and remove everything one by one until it doesn’t break anymore, isolate the problem.
Then take a look at https://github.com/webpack/webpack/issues/6929#issuecomment-403441611 for a technical on how to dissect heap dump and help find the leak.
Once you have the heapdumps you can probably also just check out the documentation of the chrome dev tools for further help.
edit: we know (and accept) there’s a small leak when using HMR, so this thread is about “unreasonable” (buggy) leaks. Not “known” leaks (like the example after 13 hours of coding, just restart when you go to pee or during lunch break and you’re good to go).
webpack 4.26.0 node 11.0.0
After dozens of hours of continuous work it crash with this error:
We made this patch-package https://gist.github.com/sibelius/baf12454c371e9d6c728376c39d9f1e0
this will make just one bundle on development mode, making it much faster and without consuming a lot of memory
we also use WPS https://github.com/shellscape/webpack-plugin-serve
I kept having core dumps because node was running out of memory during development, so I digged a bit. With my configuration, the leaks were coming from two sources:
When using favicons-webpack-plugin, for some reason, multiple instances of
Compiler
(and all the caches it references) are stored in memory and never destroyed every time a file changes. I’ll just remove this plugin during development (or maybe I’ll just find a replacement).When using
[hash]
substitutions in bundle filenames or chunk filenames, Webpack (without any plugin) is leaking memory because it stores each bundle in memory, indexed by its file name. I created a minimal repository to reproduce, please have a look. Removing[hash]
substitutions during development fixed the issue for me.I hope it can help someone. Cheers.
the problem is not with webpack-dev-server
we used to use another plugin to do the same as webpack-dev-server on this repo https://github.com/sibelius/webpack-debug, and the crash still happened when doing hmr
can we create a custom hmr strategy, and avoid the current one used by webpack?
I happens quite often if you include a large library such as Microsoft’s monaco-editor.
I think the problem is not exactly the assets, but the
Compilation
objects. AFAICT the idea ofCompilation
is that they should be needed only during a build/rebuild and disposed of shortly after.In my case, multiple
Compilation
objects were being kept around, each one with its assets and everything else. The culprit was a custom plugin that was leaking compilations by registering hooks on compiler that internally kept a reference to thecompilation
.The following is the essence of the problematic pattern.
Both hook functions are registered on the
compiler
object, but the inner one also has a closed reference tocompilation
. In this way, the short-livedcompilation
is retained in memory by thecompiler
object, which has the same lifetime of the Webpack watch-mode execution.I do not really understand why the above pattern has emerged or become problematic only with version 4.
About fixing that, webpack may provide some kind of guard for cases where hooks to
compiler
are added while handling an hook that provides access to thecompilation
and warn the plugin developer in some way.@zD98 Please create minimum reproducible test repo
@evictor Potentially, but as I understand it, it can be non-trivial to tell when things like autogenerated bundles containing split chunks are no longer needed, since these modules may only be named by hash. Or, what if your app is loaded in the browser, a file is edited which causes an async bundle to get renamed, but then in the browser, your code requests the old async chunk? It would error out unexpectedly because the requested bundle was pruned, which could seem more like a misconfiguration than expected behavior.
It could be a whole lot more effective to allow users to just opt out of using
memory-fs
, since disk space is much cheaper to consume than memory. The change is only a couple of lines.Hey there guys, I’m not sure, but it seems that I found some kind of solution for somebody. I was faced with the same problem and decide to switch off optimization field inside the development-config. And it was solution for me.
So, I guess some of this code might lead to memory leaks. Note, that there is field which contains instance of uglifyjs-webpack-plugin which was noticed earlier as one of the causes of the leaks. I hope it will useful for somebody.
I made a very small repo that has this memory leak when using react-hot-loader
https://github.com/sibelius/webpack-debug
I’m finding a combination of hot reload with devtool: ‘source-map’ causes a memory leak that takes down webpack after a handful of code changes.
I got this almost everyday. I didn’t use vue.
same when I use development mode.
mode = "none"
still blows up…I’m not sure mode is the issue.btw most of them (90%) related to cache issue’s… 5% - to old version, 4% - to old plugins, 1% - other stuff.
We were experiencing similar
heap out of memory
issues after just 5-15 HMR reloads since our upgrade to Webpack 4.We fixed it by first making sure we upgraded all loaders used by webpack, and switched out one plugin which seemed to have a memory leak when using it with webpack 4: we switched from https://github.com/jantimon/favicons-webpack-plugin to https://github.com/brunocodutra/webapp-webpack-plugin
Have you remove [chunkhash] or [hash] in filename of output option? like below,
Thanks @Sinewyk. The issue for me occurs after just 3/4 rebuilds - I wish it could last 13 hours! Also, I am not using HMR, so it wouldn’t seem related to that. The problem with reducing the build until it isolates the problem is that there is only so much I can remove before the build does not work at all - I start disabling things one by one, the problem continues, until so much is removed that the build no longer works at all. I did try installing and using headdumps, as in your minimal repro app, but it took too long to even run a single dev build that I couldn’t get to the stage where the watch would crash…
@jgcmarins I glad to be helpful.
This function takes the context of each module allowed by the test field and performs some modulations of it for creating the name of separate chunk for this module. I saw this approach here https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758. I’m not sure that it is 100% correct way to bundle splitting, but it was useful for my home-project.
I agree with @PlayMa256 , the
memory-fs
memory usage is growing much less than the process memory.still having this memory leak issue after upgrading from v3.6.0 to v4.23.1
worker-loader cause node memory leak `<— Last few GCs —>
[2054:0x39e56e0] 54189 ms: Mark-sweep 1373.9 (1460.8) -> 1373.9 (1476.8) MB, 797.7 / 0.0 ms allocation failure GC in old space requested [2054:0x39e56e0] 55136 ms: Mark-sweep 1373.9 (1476.8) -> 1373.9 (1445.8) MB, 946.1 / 0.0 ms last resort GC in old space requested [2054:0x39e56e0] 55963 ms: Mark-sweep 1373.9 (1445.8) -> 1373.9 (1445.8) MB, 827.1 / 0.0 ms last resort GC in old space requested
<— JS stacktrace —>`
This issue seems to be present while developing with hot-reload. If I look at
http://localhost:3000/webpack-dev-server
, it keeps adding hot reload files to the memory and does not cleanup the old ones. After several hot reloads result is “out of memory”.I’ve been getting this error a lot as well, happens mostly after quick css adjustments + saves.
From a vue-cli v3 project which uses webpack 4:
I also meet with this problem.I’m not sure whether it relate to ‘vue-loader’.Because it works normally without ‘vue-loader’ in one of my project.
“webpack”: “^3.6.0” The same existence
I was talking about the leak in this comment https://github.com/webpack/webpack/issues/6929#issuecomment-383591954 I’d suggest people use the Chrome tooling to trace down the leaks themselves it’s doable with some patience.
Ok, here is a minimal test case for the leak that I am experiencing.
I extracted the example from a much larger project that I am working on. The problem here seems caused by a third-party plugin,
DojoWebpackPlugin
, but in some snapshot I recall seeing other plugins that were causing the issue.It appears that webpack is keeping
Compilation
instances around, probably because of how tapable hooks are used. I don’t know the webpack source code well enough to proceed further in the investigation. See my example README for details.Guys please read https://github.com/webpack/webpack/issues/6929#issuecomment-386020396 again, we can’t solve this problem because in pure usage
webpack
no problems, i.e. problem with memory leak in some loader/plugin, please create minimum reproducible test repo if you want to solve problem fastly. Thanks!👆 since doing this, we had no more memory leaks, developing a whole day on a huge project, with steadily running webpack dev server. just to mention again…
Ps. And all that also without the split chunks plugin
Think that issue related only to chunk’s splitting interface/plugin, so, we should free old chunks which are not important after recompilation. To reproduce we should just multiplie save diff. changes, for example 5-6 changes in one second, memory gonna be freed by gc, but not at all, for example normal vue app with a lot of components gonna take near ~300mb, if we gonna save changes it’s gonna raise to 500(and cleared by gc, to 300mb again), if we gonna make to much changes it’s gonna stuck at first on 500mb, then raise to 600mb-1gb, and return to 500mb(not 300mb), so, i think that there’s only chunk splitting plugin issue.
Everyone concerned by this issue, are you using
sass-loader
?NB: Does your memory magically stop growing if you stop using
sass-loader
?