Node NextJS app recompiling when running in dev = true mode - node.js

I have an NextJS app that I build on a build server then deploy to another server to host it.
When I start the app in development mode npm wants to recompile the app even though all of the built components still exist. (.next folder, etc...)
When I run the app in a non development mode for next the app will start up with no build attempts.
Why does npm want to rebuild the app when const app = next({ true });?
In server/server.js
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
In package.json
"scripts": {
"dev": "NODE_ENV=development npm start",
"staging": "NODE_ENV=staging npm start",
"prod": "NODE_ENV=production npm start",
"build": "next build",
"start": "node server/server.js"
}
How I'm starting the app:
Development: npm run dev
Production: npm run prod

For a lack of better description the .next folder is the "optimized" version of your application. In development you need to continuously rebuild the .next folder because this is where you are serving your files from. During development you can actually see the .next rebuilding itself. In production you should only build the application once.
I imagine if you're deploying in Now it will build the .next folder as long as you have scripts like they define in setup. However, I use Docker for my builds so I have to build my .next folder via a build step. Here is an example of a Dockerfile and a corresponding package.json.
Dockerfile
FROM node:10-alpine AS builder
WORKDIR /app
COPY ./app .
RUN yarn install && yarn next-build
EXPOSE 80
CMD yarn start
package.json
...
"scripts": {
"next-build": "next build",
"start": "NODE_ENV=production node server/app.js",
...
So in production my build steps are
1. Install npm modules
2. Build my .next folder
3. Start my server.
In short:
In production since you aren't running a "next-build" script before you run "npm run prod" you aren't rebuilding the .next folder. In development next.js rebuilds each time you start your server so it can capture your changes in the .next folder.

Related

Deploy NodeJS app to GCP AppEngine with customize start command

Here is my package.json
"scripts": {
"start": "react-scripts start",
"start:develop": "env-cmd -f env/.env.develop react-scripts start",
"start:stage": "env-cmd -f env/.env.stage react-scripts start",
...
}
env folder structure
env
├─ .env.develop (env=develop)
├─ .env.stage (env=stage)
When run on local (MacOS)
"yarn start" runs NodeJS app on local with default "env" = local (which is defined in other file)
"yarn start:develop" runs NodeJS app on local with "env" = develop
But now when I want to deploy this to GCP AppEngine, it's always deploy with "start" command (equivalent to "yarn start" on local)
How can I deploy "yarn start:develop" to AppEngine without declaring more environment variables in app.yaml?
From the documentation about what happens when you deploy your program,
Node.js modules are installed in the cloud as listed in your package.json and package-lock.json files and your service is started by using npm start.
I interpret the above to mean your project on the cloud is always run with start script and GAE will not/does not know how to use another script.
A possible workaround could be to deploy your app using a different version name e.g. dev i.e. you have
Your default version with "start": "react-scripts start"
dev version with "start": "env-cmd -f env/.env.develop react-scripts start"
Both of your versions use only the start script but they do different things

Couldn't find a `pages` directory with Next.js and customer server build

I'm currently trying to create a two stage build for an application that runs with Next.js (version 12.0.6) and has a custom server for an API. I do not want to rebuild the app each single time docker runs so I copy the compiled files into the /app directory. I'd assume that the pages directory would work automatically from .next folder but unfortunately it doesn't.
While the app builds all fine, I am plagued by this issue:
Error: > Couldn't find a `pages` directory. Please create one under the project root
at Object.findPagesDir (/app/node_modules/next/dist/lib/find-pages-dir.js:33:11)
at /app/node_modules/next/dist/build/index.js:113:45
at async Span.traceAsyncFn (/app/node_modules/next/dist/trace/trace.js:74:20)
at async Object.build [as default] (/app/node_modules/next/dist/build/index.js:82:25)
My Docker file looks like this:
FROM node:lts-slim AS base
WORKDIR /base
COPY package*.json ./
RUN npm install
COPY . .
FROM base AS build
ENV NODE_ENV=production
WORKDIR /build
COPY --from=base /base ./
CMD mkdir ./pages
RUN npm run build
FROM node:lts-slim AS production
ENV NODE_ENV=production
WORKDIR /app
COPY --from=build /build/next.config.js ./
COPY --from=build /build/package*.json ./
COPY --from=build /build/.next ./.next
COPY --from=build /build/public ./public
COPY --from=build /build/dist ./dist
# RUN mkdir pages; < uncommenting this will silence the error but it's an empty fake directory
RUN npm install
EXPOSE 3000
CMD npm run start
I start the Next.js sever like this (also tried with hardcoded false for the dev property with no success):
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
And the npm commands in the project are as follows:
"scripts": {
"prestart": "next build",
"dev": "NODE_ENV=development ts-node --project tsconfig.server.json server/index.ts",
"next-dev": "next dev",
"build:server": "tsc --project tsconfig.server.json",
"build:next": "next build",
"build": "npm run build:next && npm run build:server",
"next-start": "next start",
"start": "NODE_ENV=production node ./dist/server/index.js",
"test": "jest"
},
Things I have tried so far:
Fiddling with the dir directory when creating the server. Unfortunately it seems to be correct by default pointing to the /app directly and changing it doesn't help
Fiddling with the distDir in next.config. Unfortunately the same result as above
Creating an empty pages folder in /app. This doesn't seem to work - pages are loaded from that folder and since there is nothing inside everything yields 404.
Copying the entire build into app. While this creates pages folder and works, it completely defeats the purpose of a multi-stage build.
Copying only pages folder. This fails miserably as it has dependencies on all of the other folders.
Could anyone please direct me on how to tackle this? I simply ran out of ideas and hopefully I'm missing something silly here.
Thanks!
Answering this myself as I got it to "work" and it might help someone else.
For a reason which seems to be beyond my understanding, creating a separate run script in package.json stopped Next.js to recompile itself whenever the app starts.
To reiterate on the steps taken:
Using npm start caused the entire solution to recompile.
Creating a new run line in package.json (I called it npm run go) prevents this from happens. Server spins up perfectly from the compiled js files and runs immediatelly.
It works but I have no idea why. If anyone has any insight I'm more than happy to hear it!

How to deploy a React SSR application to Heroku?

I have simple running react Server Side App .
GitHub Link for the repo, in the local env i have a build script that runs using npm start which starts the client and server builds and then i have a watcher which listen's to changes in file. This set up works really well locally.
"scripts": {
"start": "npm run dev",
"dev": "npm-run-all --parallel dev:*",
"dev:server": "nodemon --watch build --exec \"node build/bundle.js\"",
"dev:build-server": "webpack --config webpack.server.js --watch",
"dev:build-client": "webpack --config webpack.client.js --watch"
},
I tried to deploy these changes as a prod app to heroku here for some odd reason it never works and returns 503 . I have not added any changes to the build scripts in the package.json and tried deploying as is.
I thought it should work as the build log dosent give any errors on heroku but while trying to access the app it shows error and asks me to check app log but i am not using heroku cli and not planning on using it , and
thinking of auto deployment from github.
I am quite new to script/ largely build scripts trying to learn more on them.
How can we make sure this small React SSR git repo deploys and i am
able to access the home page .
I am not using heroku cli and not planning on using it
You should and I really recommend, as it's the best way to see errors that occurs after the build, why your app crashed and see the full logs. Even though you can see the logs from your heroku dashbord (More -> View logs), this only gives you the tail of the logs.
How can we make sure this small React SSR git repo deploys and i am able to access the home page.
Make sure the server is listening on the right port
by using process.env.PORT as heroku expose a dynamic port.
const port = process.env.PORT || 3000
app.listen(port, () => {
console.log('Listening on Port ' + port);
})
On heroku the NODE_ENV environment variable is set toproduction by default,
which means heroku will prune thedevDependencies after the build,
but in your case, you still need these dependencies to start your app with webpack.
You can fix this in two ways :
Customize your build process by adding a build script:
From your github
repo
:
"start": "webpack --config webpack.client.js; webpack --config webpack.server.js; node build/bundle.js"
to
"scripts": {
"start": "node build/bundle.js",
"build": "webpack --config webpack.client.js & webpack --config webpack.server.js",
"build:start": "webpack --config webpack.client.js && webpack --config webpack.server.js && node build/bundle.js",
}
Set the NODE_ENV to any other value to skip pruning your
devDependencies
heroku config:set NODE_ENV=development //(Another reason to use the CLI)
Check this link for more details

Passing environment variable to pm2 is not working

I have two API in node js using babel and I have a package.json commands to use to make the application working this is the commands:
"build": "del-cli dist/ && babel src -d dist --copy-files",
"serve": "cross-env NODE_ENV=production node dist/index.js",
"start:noupdate": "cross-env NODE_ENV=development babel-node src/index.js",
"start:serve": "cross-env NODE_ENV=production node dist/index.js",
I have two domains one is https://api.website1.com.br and another is https://website2.com.br/api.
They have the same env file name but with another data for each database, that is .env.production and .env.development
When I make this "yarn build", my Linux execute this command :
"build": "del-cli dist/ && babel src -d dist --copy-files",
And this is working fine when I try to put in production mode on my real webservers, i go to the folder from the project and run this command to make the app online with PM2:
pm2 start npm -- run-script start:serve NODE_ENV=production
That will make this command work:
"cross-env NODE_ENV=production node dist/index.js"
The app runs just fine, but I have a problem he only runs one and doesn't create a new PM2 APP he just restarts what I start.
Example if I go to the folder in my https://api.website1.com.br and run this command first in this he starts, but I go to the another he doesn't start that but reload my already early app don't create a new one, what I'm doing wrong?
I manage to work this using pm2 ecosystem, that I found in this documentation from http://pm2.keymetrics.io/docs/usage/application-declaration/
I configure the default file and put a name my APP:
module.exports = {
apps : [{
name: "app",
script: "./app.js",
env: {
NODE_ENV: "development",
},
env_production: {
NODE_ENV: "production",
}
}]
}
and use this command pm2 start ecosystem.config.js and now is working, I post here to know if someone has the same problem

How to deploy an npm project to Heroku?

I currently have an npm project built with vue-cli and socket.io server.
This is how my project is structured:
Project/
|--node_server/
| |--server.js
|--src/
| |--main.js
| |--App.vue
| |--other .vue files and folders
I do not know how to deploy this app on Heroku because I will need to run two scripts while deploying that is node server.js (in the node_server folder) and npm run build or npm run dev (in the root folder).
What are the steps on how to deploy it successfully? Heroku takes my project from github whenever I push and builds it automatically. I have tried deploying but it ends up with an error page.
Let's say you need to build the front-end with build script first, and then you need to run nodejs server with start script which is node server.js.
...
"scripts": {
"build": "gulp or something idk"
"prestart": "npm run build",
"start": "node node_server/server.js",
},
...
But if you need to run these two scripts at the same time you can achieve this with something like that:
...
"scripts": {
"build": "gulp or something idk"
"start": "npm run build & node node_server/server.js",
},
...
I hope it would be helpful.
For an example, you can take a look at the package.json of one of my project: https://github.com/hisener/pirate-radio/blob/master/package.json
For more information, please refer https://docs.npmjs.com/misc/scripts

Resources