Deploy Next.js application via PM2

I recently had the pleasure of deploying Next.js on a server using PM2. I did not find this method in the framework documentation, although I find it quite convenient, and there were very few guides on the topic. I tell you how to do everything and give working examples.

Tempting offer

At the end of spring, the team received a task to develop a web application with game mechanics for one large client. By that time, I had long wanted to try Next.js, but I still never got around to it. This time a trigger appeared – in the official React documentation, it has recently been insistently offer start projects right away on the framework, and now I couldn’t refuse.

The administrators of our north immediately suggested moving away from the deployment methods from the documentation (there are only three along with static export), and try code daemonization using PM2 instead. I had never heard of this technology before, and searching on the Internet did not give clear instructions on how to connect it with Next.js. This only made it more interesting to study the overseas contraption, and now I can share all the settings and pains of creating them.

Working with PM2

For those people like me who have never heard of PM2, it is a process manager that allows you to run NodeJS applications. Each such application-process can be restarted, stopped and monitored separately from another, and with PM2 it is convenient to distribute the load: there is cluster mode.

After installing the PM2 package on the server (in my case, for the user from whom the deployment will be performed), go to the directory of our Next.js application and create a file in the root ecosystem.config.js. There will be settings that PM2 will take to start the process. We add two main fields inside:

module.exports = {
  apps: [
    {
      name: 'Моё прекрасное приложение',
      script: 'node_modules/next/dist/bin/next'
    }
  ]
}

IN name We indicate the name of the application, it will appear in the list of processes. Next then script contains the path where PM2 will knock to launch Next.js. In my config, I additionally specified port 4000 instead of 3000 – this is reinsurance so that there are no conflicts over the default one. Additionally, you can specify exec_mode: 'cluster' to distribute the load, you can read more about this here. Here's the final look:

module.exports = {
  apps: [
    {
      name: 'Моё прекрасное приложение',
      script: 'node_modules/next/dist/bin/next',
      args: '-p 4000',
      exec_mode: 'cluster',
      instances: 'max'
    }
  ]
}

That's all, now the team pm2 start will lead to the launch of that and with the settings that we specified in the root inside ecosystem.config.js.

Nginx – start up!

I had to tinker with Nginx: at first it seemed unclear which file to direct the user to. But for everything to start, you need to lead per port, not per file. Since I chose 4000 instead of the default 3000, there are two important pieces for us nginx.conf took on this form (everything else was omitted in ellipses):

...

upstream nextjs_upstream {
  server 127.0.0.1:4000;
  keepalive 64;
}

...

location / {
  ...
  proxy_pass http://nextjs_upstream/;
  proxy_redirect off;
  proxy_read_timeout 240s;
}

...

With these settings, the 502 error was gone forever, and Nginx began to process requests correctly.

Launch Next.js

In the documentation for deploying applications on Next.js using the Node.js server, we lead two main commands:

npm run build 
npm run start

After start a server is launched with support for all Next.js features. But this is not relevant for us, because we are launching the PM2 process:

npm run build
pm2 start

What is important here is this: if we re-upload the code and execute it again npm run buildthen the PM2 process needs to be stopped with the command pm2 stop <название приложения>. Without this, I had an insidious bug that I could not catch for several days: the pipeline then successfully transitioned to passedthen spontaneously crashed due to a timeout at the stage npm run build. Moreover, the changes were uploaded to the site, which was even more confusing.

While searching on the Internet, I came across many topics in the spirit Next build hangs forever, but didn't find my solution. Later I remembered that the PM2 process both worked and continues to work during assembly, and fixing this nuance saved me from the problem forever.

That's all! Although deploying Next.js this way seemed rocky at first, I now find it a fairly convenient and fast option for running future applications on the server. I hope this article will help you comfortably develop your work using ready-made examples.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *