NestJS has become one of the most popular frameworks for building efficient and scalable server-side applications. It leverages TypeScript and modern JavaScript, making it a favorite among many developers. However, deploying NestJS applications can be daunting if you’re not familiar with the best practices and various tools at your disposal. In this article, we will dive into best practices for deploying NestJS applications seamlessly.
1. Build Optimization
Before deployment, the build process needs to be optimized. Optimize your application to ensure that you are shipping the smallest possible bundle.
Typescript Compiler Options
Optimize your tsconfig.json
to ensure that unnecessary code isn’t included:
{
"compilerOptions": {
"module": "commonjs",
"target": "es2017",
"noImplicitAny": true,
"removeComments": true,
"sourceMap": false,
"outDir": "./dist",
"rootDir": "./src",
"strict": true
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
Tree Shaking
Use tree shaking to remove dead code from your production build. This can be achieved using tools like webpack
or rollup
.
For example, using webpack
, you can create a webpack.config.js
:
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
entry: './src/main.ts',
target: 'node',
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new CleanWebpackPlugin(),
],
};
2. Environment Configuration
Use environment variables to manage different settings for development, testing, and production.
config.module
file
NestJS provides a handy library @nestjs/config
that can be used to manage configuration settings:
// src/configuration.ts
export default () => ({
database: {
host: process.env.DATABASE_HOST,
port: parseInt(process.env.DATABASE_PORT, 10) || 5432,
},
});
Validate Environment Variables
Use a validation library like class-validator
and class-transformer
to ensure that critical environment variables are set properly:
// src/env.validation.ts
import { plainToInstance } from 'class-transformer';
import { IsNotEmpty, IsNumber, IsString, validateSync } from 'class-validator';
class EnvironmentVariables {
@IsString()
@IsNotEmpty()
DATABASE_HOST: string;
@IsNumber()
@IsNotEmpty()
DATABASE_PORT: number;
}
export function validate(config: Record<string, unknown>) {
const validatedConfig = plainToInstance(EnvironmentVariables, config, {
enableImplicitConversion: true,
});
const errors = validateSync(validatedConfig, { skipMissingProperties: false });
if (errors.length > 0) {
throw new Error(errors.toString());
}
return validatedConfig;
}
3. Dockerize Your Application
Containerize your application using Docker for consistency across various environments.
Dockerfile
Here’s a basic Dockerfile for a NestJS application:
# Base image
FROM node:14-alpine
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm install --production
# Copy remaining application files
COPY . .
# Build the application
RUN npm run build
# Expose the application port
EXPOSE 3000
# Start the application
CMD ["node", "dist/main"]
Docker Compose (optional)
For more complex setups involving databases, use docker-compose
:
version: '3'
services:
app:
build: .
ports:
- '3000:3000'
environment:
DATABASE_HOST: db
DATABASE_PORT: 5432
db:
image: postgres
environment:
POSTGRES_DB: nest
POSTGRES_USER: nest
POSTGRES_PASSWORD: nest_password
ports:
- '5432:5432'
4. Continuous Integration/Continuous Deployment (CI/CD)
Automate your deployment processes using CI/CD pipelines.
GitHub Actions Example
Here’s an example using GitHub Actions to build and deploy your containerized NestJS application:
name: CI/CD
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- run: npm install
- run: npm run build
- name: Build Docker Image
run: docker build . -t my-nest-app:latest
- name: Log into Docker Hub
env:
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
run: echo $DOCKER_PASSWORD | docker login -u $DOCKER_USERNAME --password-stdin
- name: Push to Docker Hub
run: docker push my-nest-app:latest
- name: Deploy to Kubernetes
# Add deployment steps like kubectl apply -f k8s/deployment.yaml
run: echo "Deploying to Kubernetes"
Conclusion
Deploying a NestJS application can be streamlined by following best practices in build optimization, environment configuration, containerization, and CI/CD. By leveraging modern tools and methodologies, you can ensure your application is robust, scalable, and easy to maintain.
I hope you found this guide useful! Feel free to leave comments or questions below, and happy deploying!