nuxt: nuxt generate memory leak

Versions

  • nuxt: 2.14.1
  • node: v14.7.0

Reproduction

I’m using nuxt generate with the memory benchmarking from https://github.com/nuxt/nuxt.js/issues/7412#issuecomment-643195374.

I’ve reduced the generate.concurrency down to 1 and I can see in the logs that after “Generating pages with full static mode” it start’s going through my pages and the heap memory just keeps on growing.

After about 100 pages generated it runs out of heap memory FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory.

I’m using 3GB of heap memory with node --max_old_space_size=3072 ./node_modules/.bin/nuxt generate, sure I could increase this but with hundreds of pages it’s not scalable.

This wasn’t happening in the older version of nuxt 2.12.2

What is Expected?

I expect that generating pages would have roughly flat memory usage and not keep on growing with each generated page.

What is actually happening?

Memory usage keeps growing with each generated page.

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Reactions: 6
  • Comments: 46 (11 by maintainers)

Commits related to this issue

Most upvoted comments

Same problem! Nuxt generates 1/5 pages, freezes, eats up all memory and crashes. Last normally working version for me 2.12+

@pi0 I spent a few hours reducing my project to a minimally reproducing example.

https://github.com/andrewharvey/nuxt-bug-7855

Running yarn run generate the memory will keep growing for each page and never come down, all the way until running out of space. Increasing max_old_space_size might buy you a couple extra pages, but that’s not scalable and doesn’t address the root cause.

There are still a few pieces but I’ve hit the point where if I take something out I don’t see the issue anymore, so it’s hard to work out what exactly is causing it.

UPDATE: though if I replace https://github.com/andrewharvey/nuxt-bug-7855/blob/master/store/index.js#L15 with the similar bit from earlier in the file then looks like the issue goes away…

I just spent a whole day trying to optimize what I thought was a leaky application. I’m increasingly certain that the problem lies with Nuxt, especially hearing I’m not the only one. Over the course of debugging memory consumption, I can see that even after the generate process has completed, our generate process leaves over 2GB sitting in heap.

Our application is fetching fairly large payloads in the fetch method, across most routes of a fairly large site (many hundreds of routes). If I limit the amount of data that is being fetched here, the problem is less noticeable. Thus the problem seems to scale both with the amount of data being fetched and the number of routes being generated.

I’m facing the same issue guys, almost spent 3 days without any good luck to find a solution

Hoping that this may help others: in our case the memory leak was caused by global Vue.mixin({…}) inside custom plugins.

The correct implementation of a global mixin is here: https://nuxtjs.org/docs/2.x/directory-structure/plugins/#global-mixins

if (!Vue.__my_mixin__) {
  Vue.__my_mixin__ = true
  Vue.mixin({ ... }) // Set up your mixin then
}

I would like to call attention here, is this maybe something that Nuxt or Vue should do automatically? I do not think we should trust developers to read the whole documentation of the framework before implementing a global mixin properly. I would say a run time warning in console, a build time error or a linter error could be implemented. If this causes severe memory leaks, why there is not a way of applying some kind of singleton pattern so a mixin cannot be defined more than one time. Is there a reason why it should be allowed to define a mixin more than once?

@andrewharvey To add to the above, as far as I can tell the specific memory leak you’ve identified is caused by Vuetify rather than Nuxt (cc: @kevinmarrec). I haven’t been able to confirm that in your case @AliasIO - if you can get in contact with an API key so I can generate routes locally for your site I’d be grateful.

If anyone in this thread who has encountered a memory leak like this and is not using Vuetify I’d welcome a reproduction or more information.

I’m looking into this and will update this comment with my current thinking, which undoubtedly will change.

I can replicate this issue using the repo above - with the CLI - as long as there is an initial build (you can also force this on subsequent builds by setting generate.cache to be false). However, running generation programmatically does not appear to result in a memory leak (and is also considerably faster):

const { Builder, Generator, Nuxt } = require('nuxt-edge')
const config = require('./nuxt.config.js')

async function main() {
    const nuxt = new Nuxt({
        ...config,
        dev: false
    })
    await nuxt.ready()
    const builder = new Builder(nuxt)
    const generator = new Generator(nuxt, builder)
    await generator.generate()

}

main()

After 3 days of attempting some of the solutions outlined above, lots of additional searching and trial/error (and lots of cussing), the culprit for me was a watch being initiated within a global composable on server side, thus being initiated on every single SSG route. Wrapping the watcher with process.client condition fixed all my problems.

@danielroe Unfortunately switching to nuxt-edge did not make a difference. Even downgraded from Node 15.x to Node 14.x and reinstalled all npm packages for the project. But now even the index page refuses to load. Perhaps this would deserve a separate issue since it is not the same issue as discussed here 😃

@danielroe apologies for the ping once again, I managed to isolate the issue down to why nuxt generate was freezing for me, it was because for some reason (that I have not discovered yet), my await method within asyncData is no longer working and for some reason waiting (and hence causing the freezing of nuxt generate) as it was working in nuxt: 2.13.3. Not related to this issue, my sincere apologies.

Hoping that this may help others: in our case the memory leak was caused by global Vue.mixin({…}) inside custom plugins.

The correct implementation of a global mixin is here: https://nuxtjs.org/docs/2.x/directory-structure/plugins/#global-mixins

if (!Vue.__my_mixin__) {
  Vue.__my_mixin__ = true
  Vue.mixin({ ... }) // Set up your mixin then
}