Nuxt.js: App crashes on ServerMiddleware hot reload if Mongoose models are used, gives an error like "ServerMiddleware Error: Cannot overwrite User model once compiled"

Created on 14 Aug 2020  路  9Comments  路  Source: nuxt/nuxt.js

Versions

  • nuxt: v2.14.1
  • node: v12.18.3

Reproduction

Use this project to reproduce, you may need to add a working MongoDB database credentials in .env file.

Steps to reproduce

npm install
npm run dev
(No error at this point yet)
Make a change in login.js file
Save

What is Expected?

Normal hot reload of servermiddleware as always (like when Mongoose is not used).

What is actually happening?

App crashes with this error:

ERROR ServerMiddleware Error: Cannot overwrite User model once compiled.

bug-report

Most helpful comment

fixed by v2.14.4 @kamran-12 now you should be able to normally use serverMiddleware without HMR issues with mongoose :)

All 9 comments

This isn't related to Nuxt, This is mongoose error. When a change occurs and Nuxt reload model files and mongoose models call twice.

Here you can find a fix: https://stackoverflow.com/questions/19051041/cannot-overwrite-model-once-compiled-mongoose

@farnabaz This is actually a problem with how reloads are implemented with nuxt. I looked at the stackoverflow example you gave me before starting to write this bug report, and although error is same, reasons for it are different.

In stackoverflow example: person with name Anathema.Imbued made a mistake by defining the same model twice within the project, got error immediately (not just on reload).

In my example: didn't do such mistake, same mongoose code works well outside nuxt, also works well inside nuxt until reload. Crashes only during hot reload of server middleware.

Hot reloads of server middleware should be done exactly like nodemon.

Please re-open.

Nodemon restarts the whole server on file change, but Nuxt removes the cache and re-import the file. I believe this is not a bug its nuxt approach to reload files.
Restarting the server on every file change has a great impact on performance.

You can avoid mongoose error by checking models to see if User model was registered or not.

let modelName = ...
let schema = ...
const Model = mongoose.models[modelName] || mongoose.model(modelName, schema);

export default Model;

This issue is both with nuxt HMR and mongoose. Using default connection, it keeps instance in CJS cache and when reloading app, it causes this error

You can avoid mongoose error by checking models to see if User model was registered or not.

@farnabaz I guess this will cause not applying schema changes.

One workaround is doing full reload for server by directly importing serveriMiddleware like this:

export default {
  serverMiddleware: [
    require('./api')
  ]
}

Maybe we can also introduce an option to HMR some node_module dependencies. Currently we don't clear cache for all node_modules (src) which is also not configurable but if it is, we can specify mongoose or other HMR incompatible dependencies.

I guess this will cause not applying schema changes.

Yes, you are right.

we can specify mongoose or other HMR incompatible dependencies.

Do you mean to hardcode mongoose and other dependencies?

@pi0

@pi0 what can be a temporary solution for me? So that when something inside servermiddleware changes, all of the servermiddleware (but not the whole nuxt server) restarts (like nodemon)? That would be good enough for me (as nodemon restart takes ~1 sec., while full nuxt restart takes 5 to 10 sec (that needs improvement, too, btw)). I guess what you suggested was supposed to be what I am asking for right now, but it does not work (the same error is still there).

Do you mean to hardcode mongoose and other dependencies?

@farnabaz That could be a quick nice patch by modifying regex

What can be a temporary solution for me?

@kamran-12 Using require as mentioned above, will cause full restart. HMR is to only replace some requires on runtime to avoid full restart. Alternatively before fix for mongoose, you can use concurrently to run API standalone and make requests from UI to it. (can provide more detailed info how to do)

@pi0 if I understood right, you suggested to replace serverMiddleware: [{path: '/api', handler: '~/api/index'}] to serverMiddleware: [require('./api')] in nuxt.config.js. It didn't work. The error didn't go away. I have said this in the last sentence of my previous comment.

Alternatively before fix for mongoose, you can use concurrently to run API standalone and make requests from UI to it. (can provide more detailed info how to do)

That would be helpful.

fixed by v2.14.4 @kamran-12 now you should be able to normally use serverMiddleware without HMR issues with mongoose :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

o-alexandrov picture o-alexandrov  路  3Comments

mikekidder picture mikekidder  路  3Comments

danieloprado picture danieloprado  路  3Comments

VincentLoy picture VincentLoy  路  3Comments

mattdharmon picture mattdharmon  路  3Comments