mismatch BUILD_ID in multi server #786
I have two server running a next program for load balancing, when I run
@n8agrin What do you mean by the lockfile of deps? yarn.lock?
As an easy fix, we could provide a way to override the build id.
referenced this issue
Jan 16, 2017
You meant to mention me ? :D
yep, I meant
Another problem of the current approach is that build artifacts would be invalidated even if you just updated custom server and served content was not changed at all, for example.
As another approach to generate
Okay I was about to raise an issue for this and so wrote something up. Rather than creating a new ticket, I'll just paste it here (apologies for labouring over the same thing as above, but have some additional info and comments that might be relevant/helpful).
I am using Next.js on a couple of new projects (some with public source code, some private). On one of the projects I've run into an issue deploying on a scaling cluster on AWS Elastic Beanstalk, althought the problem is not AWS or EB specific. I've got suggestion for a fix but wanted to run it by folks first.
With the sort of deployment system with EB, I'm deploying a git repo and it runs
When each server in the cluster (in AWS terminology "Scaling Group") runs it's own build step it generates it's own unqiue hashes for files in .next, these hashes are not the same as on other servers, even though the code is identical.
So, when a user loads the site, it will request resources dynamically (like the JS files that are automatically generated by Next.js) BUT because they happen over seperate HTTP requests they may be served by different servers.
This means that you get HTTP 5000 "Internal Server" errors when the client tries to load a page, because it references resources with server specific hashes in them like:
ABSOLUTE PATHS IN .next/dist/pages/index.js
I thought I could address the issue by bundling a pre-built .next assets folder with each deploy, but that doesn't work well as '.next/dist/pages/index.js' includes absolute (not relative) paths so then running 'npm start' on the server fails because it can't find the files it's referencing because the absolute path to the modules it's referencing are not the same between the computer the assets are pre-built on and the server.
For example, references like this:
Would then look something like this:
This seems to work fine and be low impact, so if people think that seems sane I'm happy to submit a pull request that does that.
[NB: So far I have only changed these manually with a regex and not programmatically.]
Personally I'd prefer this (either instead or as well - in some environments option 1 would be preferable, but in my case option 2 is even better), but I don't know the codebase and so am unsure of the ramifications. This is what is suggested above.
I see this has already been suggested. This is a decent workaround and is what I've done for now - but it's not ideal for building a scaleable service and it won't be an option open to everyone (as some switches don't support it and/or enabling it can come with limitations).
I agree the idea of build once, run many instances is nice, but (sadly) lots of deployment systems don't work that way out of the box and can be a pain to achieve in production.
I am relieved to find out I'm not the only one having this as an issue at least. :-)
For the buildId, sticky session is a good solution, but it's not for scaling. So, we need to go for something else.
But for the short term, I'd like to show you a way to override the
"postbuild": "echo MY_NEW_ID > .next/BUILD_ID",
And you can also get the BUILD_ID via env variables like this too:
"postbuild": "echo $BUILD_ID > .next/BUILD_ID",
@arunoda Thanks again, I've updated to beta 18 in production (with a green/blue deployment method) and using this approach is working well.
Details for the record, in case it helps others:
Annoyingly, it turns out the auto-generated app version is not available as an environment variable (though you can get it by looking for and unzipping a file at a specific location, or calling the AWS API from the host) so I opted instead to just grab the app version from package.json and echo that to .next/BUILD_ID.
Due to AWS Elastic Beanstalk only supporting one of a range of specific commands start the server (i.e. you can tell it to do 'npm start' but not 'npm run build; npm start') my package.json contains a script that now looks like this:
It seems that being able to just pass a Build ID as an option if invoking next() from a JS file might be nice way to let people in similar situation set the ID if they want to in a simple way (using whatever logic they want without bloating next). Of course, they could equally just write their own logic to write to the BUILD_ID file themselves before calling next(), but the option to pass it explicitly would make for a simple self-documenting mechanism.
Of course EBS is slow for deployment and something like Zeit's now platform is both faster much less hassle, but for anyone building front ends in enterprise environments (in my case, because I want to leverage AWS specific features on the back end) I'm happy to say the provided solution works just fine - and it's now in production and I've been able to turn sticky load balancing back off.
referenced this issue
Mar 7, 2017
I got this working with AWS EBS without Docker using the git hash. I had an issue with something like @rickysahu's solution because
You can get around this by using
My working solution
"prestart": "NODE_ENV=production next build && cp -a build/. .next/", "start": "NODE_ENV=production node server.js"
referenced this issue
Feb 23, 2018
Update to get this working with AWS EBS without Docker using the git hash and the new
Updated working solution
"prestart": "NODE_ENV=production next build", "start": "NODE_ENV=production node server.js"