After creating a Next.js application, a key stage is deploying it to the production environment. In this module, we will look at various hosting platforms that offer an optimized environment for Next.js applications, with a particular focus on Vercel - the platform created by the Next.js authors.
Vercel is a platform that offers the best native support for Next.js applications, as both technologies are developed by the same company. This ensures optimal support for all Next.js features, automated deployments, and a global CDN.
Before deploying, ensure that your project is ready for production:
next build locally to check for potential errorsCreate an account on Vercel
Import the project
Deployment configuration
Deployment
Deployment verification
To configure a custom domain for your project on Vercel:
One of Vercel's greatest strengths is the automatic deployment system:
Automatic production deployments
main) triggers an automatic deploymentPreview Deployments
1// Example of Next.js configuration optimized for Vercel
2// next.config.js
3
4module.exports = {
5 // Image optimization - automatically handled by Vercel Image Optimization
6 images: {
7 domains: ['example.com', 'images.unsplash.com'],
8 },
9
10 // Integrated Vercel analytics
11 vercelAnalytics: {
12 enabled: true,
13 },
14
15 // Internationalization settings
16 i18n: {
17 locales: ['pl', 'en', 'de'],
18 defaultLocale: 'pl',
19 },
20};Vercel offers a range of advanced features worth using:
Netlify is another popular platform that offers excellent support for Next.js applications, especially after the introduction of the Netlify Next.js Runtime feature.
1# netlify.toml
2[build]
3 command = "npm run build"
4 publish = ".next"
5
6[[plugins]]
7 package = "@netlify/plugin-nextjs"1npm install -D @netlify/plugin-nextjs
2# or
3yarn add -D @netlify/plugin-nextjsCreate an account on Netlify
Import the project
Deployment configuration
npm run build or yarn build.nextConfigure environment variables
Deployment
Netlify offers a range of unique features that can be useful in Next.js projects:
1// Example of using Netlify Functions with Next.js
2// /netlify/functions/hello-world.js
3
4exports.handler = async function(event, context) {
5 return {
6 statusCode: 200,
7 body: JSON.stringify({ message: "Hello World" }),
8 headers: {
9 'Content-Type': 'application/json'
10 }
11 };
12};
13
14// Access from the Next.js application
15// pages/api-example.js
16import { useState, useEffect } from 'react';
17
18export default function ApiExample() {
19 const [data, setData] = useState(null);
20
21 useEffect(() => {
22 fetch('/.netlify/functions/hello-world')
23 .then(res => res.json())
24 .then(data => setData(data));
25 }, []);
26
27 return (
28 <div>
29 <h1>API Example</h1>
30 <pre>{JSON.stringify(data, null, 2)}</pre>
31 </div>
32 );
33}AWS Amplify is a service from Amazon that also offers good support for Next.js applications, especially if you already use the AWS ecosystem.
1# amplify.yml
2version: 1
3frontend:
4 phases:
5 preBuild:
6 commands:
7 - npm ci
8 build:
9 commands:
10 - npm run build
11 artifacts:
12 baseDirectory: .next
13 files:
14 - '**/*'
15 cache:
16 paths:
17 - node_modules/**/*Create an AWS account or log in to an existing one
Go to the AWS Amplify console
Connect the repository
Build settings configuration
Configure environment variables
Deployment
One of the main strengths of AWS Amplify is easy integration with other AWS services:
1// Example: Integration with AWS Lambda and DynamoDB
2// pages/api/users.js
3
4import { DynamoDB } from 'aws-sdk';
5
6const dynamoDB = new DynamoDB.DocumentClient();
7
8export default async function handler(req, res) {
9 if (req.method === 'GET') {
10 const params = {
11 TableName: process.env.DYNAMODB_TABLE_NAME,
12 };
13
14 try {
15 const data = await dynamoDB.scan(params).promise();
16 res.status(200).json(data.Items);
17 } catch (error) {
18 res.status(500).json({ error: 'Failed to fetch users' });
19 }
20 }
21}Digital Ocean App Platform is another hosting option that offers good support for Next.js applications.
Create a Digital Ocean account or log in to an existing one
Go to Digital Ocean App Platform
Select the code source
Application configuration
Adjust the settings
npm run build or yarn buildnpm start or yarn startFinalization
For statically generated Next.js applications, you can use GitHub Pages with GitHub Actions:
1# .github/workflows/deploy.yml
2name: Deploy to GitHub Pages
3
4on:
5 push:
6 branches: [ main ]
7
8jobs:
9 build:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v2
13 - uses: actions/setup-node@v2
14 with:
15 node-version: '18'
16 - name: Install dependencies
17 run: npm ci
18 - name: Build and export
19 run: npm run build && npm run export
20 - name: Deploy
21 uses: peaceiris/actions-gh-pages@v3
22 with:
23 github_token: ${{ secrets.GITHUB_TOKEN }}
24 publish_dir: ./out1// next.config.js
2module.exports = {
3 output: 'export',
4 basePath: '/repository-name', // If the page is not on the main domain
5 images: {
6 unoptimized: true, // For GitHub Pages
7 },
8};1{
2 "scripts": {
3 "export": "next export"
4 }
5}Firebase Hosting is another option, especially if you use other Firebase services:
1npm install -g firebase-tools1firebase login
2firebase init hosting1{
2 "hosting": {
3 "public": "out",
4 "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
5 "rewrites": [
6 {
7 "source": "**",
8 "destination": "/index.html"
9 }
10 ]
11 }
12}1npm run build
2npm run export
3firebase deployIf you prefer to host the application on your own server:
1{
2 "scripts": {
3 "start": "next start -p $PORT"
4 }
5}1npm install -g pm2
2pm2 start npm --name "next-app" -- start1server {
2 listen 80;
3 server_name yourpage.com www.yourpage.com;
4
5 location / {
6 proxy_pass http://localhost:3000;
7 proxy_http_version 1.1;
8 proxy_set_header Upgrade $http_upgrade;
9 proxy_set_header Connection 'upgrade';
10 proxy_set_header Host $host;
11 proxy_cache_bypass $http_upgrade;
12 }
13}1# Dockerfile
2FROM node:18-alpine AS base
3
4# Dependency installation stage
5FROM base AS deps
6WORKDIR /app
7COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
8RUN
9 if [ -f yarn.lock ]; then yarn --frozen-lockfile;
10 elif [ -f package-lock.json ]; then npm ci;
11 elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i;
12 else echo "No lockfile present" && exit 1;
13 fi
14
15# Build stage
16FROM base AS builder
17WORKDIR /app
18COPY /app/node_modules ./node_modules
19COPY . .
20RUN npm run build
21
22# Production stage
23FROM base AS runner
24WORKDIR /app
25ENV NODE_ENV production
26
27RUN addgroup --system --gid 1001 nodejs
28RUN adduser --system --uid 1001 nextjs
29
30COPY /app/public ./public
31COPY /app/.next/standalone ./
32COPY /app/.next/static ./.next/static
33
34USER nextjs
35EXPOSE 3000
36ENV PORT 3000
37
38CMD ["node", "server.js"]1// next.config.js
2module.exports = {
3 output: 'standalone',
4};1docker build -t next-app .
2docker run -p 3000:3000 next-appManage environment variables according to Next.js best practices:
Distinguish between client and server variables:
NEXT_PUBLIC_Environment files:
.env.local - variables for the local environment, not committed to the repository.env.development - variables for the development environment.env.production - variables for the production environment.env.test - variables for the test environmentCache and CDN:
Compression:
Core Web Vitals:
1// next.config.js - production optimization
2module.exports = {
3 // Compression
4 compress: true,
5
6 // Image optimization
7 images: {
8 domains: ['images.example.com'],
9 formats: ['image/avif', 'image/webp'],
10 },
11
12 // Static generator - maximum performance for ISR/SSG pages
13 staticPageGenerationTimeout: 120,
14
15 // Production optimization
16 productionBrowserSourceMaps: false, // Disable source maps in production
17
18 // webpack configuration
19 webpack: (config, { dev, isServer }) => {
20 // webpack optimizations...
21 return config;
22 },
23};Consider implementing Continuous Deployment (CD) to automate the deployment process:
1# GitHub Actions - deploy.yml
2name: Deploy
3
4on:
5 push:
6 branches: [ main ]
7
8jobs:
9 deploy:
10 runs-on: ubuntu-latest
11 steps:
12 - uses: actions/checkout@v2
13
14 - name: Setup Node.js
15 uses: actions/setup-node@v2
16 with:
17 node-version: '18'
18
19 - name: Install dependencies
20 run: npm ci
21
22 - name: Run tests
23 run: npm test
24
25 - name: Build project
26 run: npm run build
27
28 - name: Deploy to production
29 uses: amondnet/vercel-action@v20
30 with:
31 vercel-token: ${{ secrets.VERCEL_TOKEN }}
32 vercel-org-id: ${{ secrets.ORG_ID }}
33 vercel-project-id: ${{ secrets.PROJECT_ID }}
34 vercel-args: '--prod'Next.js application deployment can be done in many ways, depending on the project's needs and the team's preferences:
The choice of hosting platform should be tailored to:
Regardless of the chosen platform, it's worth following best practices for managing environments, environment variables, security, and deployment automation.