Should you host Next.js yourself?

Laurens Mesure
12 min readFeb 7, 2022

--

Next.js is a wrapper of the React.js library. It enables React-based web applications to be run server-side and generate static websites.

What is Next.js?

Next.js was first launched on October 25, 2016. It’s an open-source project based on Node.js. It enables some extra features on top of React.js such as server-side rendering, static site generation, image and font optimization, Search Engine Optimization features, … The project is currently owned and maintained by Vercel (previously named ZEIT). Vercel leads the open-source development of the project, as well as other services.

Next.js wouldn’t be possible without Node.js. Node.js is an open-source, cross-platform, back-end JavaScript runtime environment that runs on the V8 engine and enables users to execute JavaScript code outside the web browser. It follows the JavaScript everywhere paradigm. Unifying web application development around a single programming language, rather than different languages in the backend and frontend.

Next.js uses Node.js to create a React.js library to enable the advanced features that are not available in the standard React.js package.

Why would you want to use Next.js?

Next.js offers a whole suite of features that are not available with the standard React.js package. For example, you cannot add advanced search engine optimization on a per-page basis. You can only edit the head tag and its content one time on the index.js page.

Another strong feature of Next.js is static image optimization. Conventionally, a user would upload an image and the server would create multiple copies of the image in different resolutions according to the resolutions that are used on the website. Next.js automates this and converts every image or icon to the correct resolution (server-side) and displays them in the next generation WebP format. The results in faster load times because the browser receives the correct image format, which reduces file size and the browser doesn’t have to scale the image any further.

Internationalization is also built-in with 2 different strategies and 1 automation technique: per domain routing, subdomain routing and automatic language detection. Using server-side rendering, the translations can be done server-side and thus be statically generated for future use. This can improve SEO in different languages, and you will notice a performance increase. When the user makes a request to the site, Next.js can analyze this request to determine the preferred language. It then routes you to the correct subdomain or route with the correct prefix.

A more advanced feature of Next.js is incremental Static Regeneration, hybrid SSG and SSR. Incremental Static Regeneration can be used in webshops. For example, you have a product list and an administrator adds a new product. This product would be eligible for static site generation because the product attributes probably won’t change a lot over time. All products are thus statically generated, but static site generation only runs at build time. Next.js cannot determine when a product is added or when it should create a new product page for that item. Therefore, you can give some sort of template that will be sent to the browser whilst Next.js is generating the full content of that page. When it’s done generating the static site, it will send the result to the browser and store the newly generated page on the server. When another user clicks on the newly added product, the user won’t have to wait so long because it was already generated before.

You can combine this type of technique with SSR (Server-side rendering). For example, you render the page differently on every request. When the user sends a request to the server, it builds the page server-side dynamically with the info that was acquired by the request and sends it to the user. This differs from the SSG (Static site generation) technique that builds the page on build-time and stores it on the server. SSR builds the page on every request, and SSG only builds the page on build time and saves it for future use.

What hosting options do you have?

Next.js is built and maintained by a company named Vercel. Vercel offers you multiple services and one of them is hosting. You can get free hosting if you want to host a hobby project, but when you want to host commercial applications or sites you have to use a different tier. It costs about 20 dollars per month. With this tier, you can have a team of up to 2 members, if you need more then you have to go another tier higher and inquire about pricing.

https://vercel.com/pricing

Their tagline is “A Great Experience is Priceless”. After using their product for about a year, I can vouch for the quality of their service. It is really easy to set up and easy to maintain. You get a dashboard where you can see the different builds, commits, settings, … In a blink of an eye.

How to set up a Next.js project and host it on Vercel?

Foremost, we have to create a Next.js project. I’ve added TypeScript because it makes JavaScript development easier by enabling typed objects. When executing this command, you need to give the project a name. I have chosen tutorial as the name for this project.

yarn create next-app --typescript

After this command, you get a default project that’s filled with some boilerplate code. Notice that the files are not in a subdirectory tutorial. This is the name you have given to the project. To run the Next.js server locally for development, you can enter the directory and start the server:

cd tutorial
yarn dev

The result looks something like the following. When you surf to http://localhost:3000, you will see your new site!

Now you can develop your site locally until you’re satisfied with the result. Note that not all the SSR or SSG features are enabled in development mode, this would require you to build your site again and again upon a save. When you develop the site you are probably using something like GitHub to keep track of different features, bugs and version changes. If you’re not doing all that with some type of software, set it up now. You really should keep track of all the changes.

Vercel

Go ahead now and create an account on Vercel.com. You are now dropped either in your project overview or on a form to create a new project. It will look something like this:

If you are not on the “New project” page, go ahead and click on the big white button at the top right that says “+ New Project”. Go ahead and select your desired project. After that Next.js will give you a few parameters to configure, but we can leave this all to the defaults. Go ahead and click deploy. And that’s it! Your project is deployed!

As you can see, the experience is really great and easy to set up. Even for more advanced use-cases, we can configure multiple parameters to accommodate the needs of the project.

On-premise hosting: Next.js

You might want to host Next.js on-premise for a couple of reasons. You can deploy it as a microservice in your own virtual environment. When deployed as a microservice, it’s easier to load balance the frontend by dynamically spinning up more containers when required. You have full control over the environment, and you can tweak it to your own specific needs. You can aggregate multiple log files to a single analytics server, … But this comes with its own downsides, you have to manage the entire environment yourself, which can cost a lot in servers or personnel costs. The security has to be handled by your team, and it has to be monitored by your own team. For me, the ideal strategy is to host these microservices in the cloud on services such as AWS or Azure.

How to host Next.js on a Debian server?

We will continue from the project we just created in Visual Studio Code (or your own preferred text editor). I’m not going to go over the installation of a Debian server. We will be using a fresh installation of Debian 11 in this tutorial. If you’re not following along with a fresh installation of Debian, make sure to update your machine first!

sudo apt-get update && sudo apt-get upgrade

First, we will install all the required packages for the Next.js setup. I’ll explain later what each command does.

sudo apt-get install git nodejs npm nginx -y
npm install -g yarn
yarn global add pm2

We have installed Git to pull our code from the GitHub repository, Node.js is required for NPM, yarn and Next.js. It’s basically the base of the entire project. NPM is a package manager for Node.js, using this we can install yarn. Yarn is a newer package manager that has better build times and has a smaller footprint on the repo than NPM. Lastly, we have installed Nginx. Nginx is a popular web server that routes incoming requests to the correct destinations. In this tutorial, we also installed pm2. It is a tool that manages Node.js applications, and it has a built-in load balancer.

We can create a directory for our project to live. The convention is to do that in the /var/www/ folder. We will follow the convention in this tutorial by creating a folder called tutorialFolder.

mkdir /var/www/tutorialFolder
cd /var/www/tutorialFolder

We pull in the code from the Git repository using the following command:

git clone https://github.com/TheProjectLCompany/nextjs-tutorial.git .

The “.” after the command is to pull the code in the current working directory. The default behaviour is to create a new folder with the repository name and put all the code in that folder. This is not needed for this tutorial.

We now have the code on our own server. It is now time to build our project using the following commands

yarn
yarn build

When this is completed you will get a nice overview of how much storage space the website consumes, this can also indicate what a user is expected to download to access the website.

yarn run v1.22.17
$ next build
Attention: Next.js now collects completely anonymous telemetry regarding usage.
This information is used to shape Next.js' roadmap and prioritize features.
You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:
https://nextjs.org/telemetry
info - Checking validity of types
info - Creating an optimized production build
info - Compiled successfully
info - Collecting page data
info - Generating static pages (3/3)
info - Finalizing page optimization
Page Size First Load JS
┌ ○ / 5.45 kB 75.6 kB
├ └ css/149b18973e5508c7.css 655 B
├ /_app 0 B 70.2 kB
├ ○ /404 194 B 70.4 kB
└ λ /api/hello 0 B 70.2 kB
+ First Load JS shared by all 70.2 kB
├ chunks/framework-6e4ba497ae0c8a3f.js 42 kB
├ chunks/main-101cfeaa18eb0e64.js 26.9 kB
├ chunks/pages/_app-ca6aae25bc99a05f.js 491 B
├ chunks/webpack-69bfa6990bb9e155.js 769 B
└ css/27d177a30947857b.css 194 B
λ (Server) server-side renders at runtime (uses getInitialProps or getServerSideProps)
○ (Static) automatically rendered as static HTML (uses no initial props)
Done in 11.06s.

Now we can start to think about how the user is going to access our site. That is handled by the Nginx web server, Nginx doesn’t know yet what to serve and where to look for it. We tell it by creating a file in the following directory using this command. Note: “tutorial.be” is just a name, another valid name could be “abcdef” or “a”

nano /etc/nginx/sites-availalbe/tutorial.be

In the text editor, you can paste the following

server {
listen 80;
server_name tutorial.be www.tutorial.be;root /var/www/tutorialFolder;
access_log /var/log/nextjs/access.log;
error_log /var/log/nextjs/error.log error;
index index.html index.htm;location /_next/ {
alias /var/www/tutorialFolder/.next/;
expires 30d;
access_log on;
}
location / {
proxy_pass http://127.0.0.1:3000;
proxy_read_timeout 60;
proxy_connect_timeout 60;
proxy_redirect off;
# Allow the use of websockets
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}

The only parameters you would want to change is:

  • server_name, it indicates what domain names the server should listen for
  • root, it tells where Nginx can find your website
  • access_log, the location where the access log should be stored (the path has to exist for this to work)
  • error_log, the location where the error log should be stored (the path has to exist for this to work)
  • inside the “location /_next/” block of the alias variable, it points to the root of your project + the hidden next folder

You can close the editor using the “CTRL+ x” then “y” to confirm changes and “enter”. We have created a config file for our website, but it doesn’t immediately tell Nginx that this site is enabled. Think of it as a “draft”. We can now create the access and error log directories using the following command

sudo mkdir /var/log/nextjs

Now we can tell Nginx to enable the site using the following commands

sudo ln -s /etc/nginx/sites-available/tutorial.be /etc/nginx/sites-enabled/
sudo nginx -t
sudo nginx -s reload

The “nginx -t” command will check the config for errors. If this returns errors, you have to fix them before running “nginx -s reload”. Because if you reload the file with errors in the config file, you will break the Nginx routing for that site.

Now we only have one more command to run, and we are all set up. Pm2 will handle the requests and pass them along to Next.js, it also has a built-in load balancer that is automatically configured.

cd /var/www/tutorialFolder/
pm2 start yarn --name "nexttutorial" -- start

We get a nice overview of PM2 and various handy commands. The app will be launched on localhost port 3000 (the default port, but you can change this in the package.json by modifying the start command to something like “next start -p 8000”). If you try to go to tutorial.be, you will see that it fails. You still have to configure the DNS to point to your server, you can do it locally on Windows by modifying the hosts file to something like this

192.168.18.129    tutorial.be

Now, if we surf to tutorial.be, we will see our Next.js website.

Conclusion

Hosting Next.js is not as hard as it used to be. It is far more documented than a couple of years ago. The benefits might outweigh the cons for you to consider hosting Next.js yourself. But, the easiness of Vercel might be more suited for smaller operations or businesses. I would recommend small businesses to consider using Vercel (don’t forget it costs 20 dollars per month). Medium-sized businesses should consider hosting the backend and frontend on a cloud provider such as Amazon AWS or Microsoft Azure, creating microservices for the backend, frontend, logging service, security services and routing service. For larger businesses, I would recommend either using the strategy for medium-sized businesses or fully on-premise servers virtualized with something like VMWare ESXi & VSphere. You should virtualize microservices and containerize them with something like Docker.

Next.js is a great tool that I’ll be using a lot in the future, I’m excited about the changes it will bring in the future.

Sources

Deployment | Next.js. (2022). Next.Js Deployment. https://nextjs.org/docs/deployment

Modify your hosts file -. (2011, March 16). Rackspace. Retrieved February 7, 2022, from https://docs.rackspace.com/support/how-to/modify-your-hosts-file/

NGINX, Inc. (2022, February 1). Advanced Load Balancer, Web Server, & Reverse Proxy. NGINX. https://www.nginx.com/

R. (2021a, August 29). How to Install Yarn on Debian 11 / Debian 10. ITzGeek. Retrieved February 7, 2022, from https://www.itzgeek.com/how-tos/linux/debian/how-to-install-yarn-on-debian-11-debian-10.html

R. (2021b, October 5). How To Install Node.Js on Debian 11. TecAdmin. Retrieved February 7, 2022, from https://tecadmin.net/how-to-install-node-js-on-debian-11/

Setup a Next.js project with PM2, Nginx and Yarn on Ubuntu 18.04. (2022). Will & Skill — Digitalbyrå i Stockholm. https://www.willandskill.se/en/setup-a-next-js-project-with-pm2-nginx-and-yarn-on-ubuntu-18-04/

V. (2020, February 25). Does Next.js support pm2 cluster mode? · Discussion #10675 · vercel/next.js. GitHub. Retrieved February 7, 2022, from https://github.com/vercel/next.js/discussions/10675#discussioncomment-51387

Wikipedia contributors. (2022a, January 22). Next.js. Wikipedia. https://en.wikipedia.org/wiki/Next.js

Wikipedia contributors. (2022b, February 6). Node.js. Wikipedia. https://en.wikipedia.org/wiki/Node.js

Yarn install command error No such file or directory: “install.” (2017, September 2). Stack Overflow. https://stackoverflow.com/questions/46013544/yarn-install-command-error-no-such-file-or-directory-install

--

--