{
  "slug": "Best-Practices-for-Developing--Deploying--and-Managing-NestJS-Applications-cef0edc4681f",
  "title": "Best Practices for Developing, Deploying, and Managing NestJS Applications",
  "subtitle": "The document covers several important aspects of developing, deploying, and managing a NestJS application:",
  "excerpt": "The document covers several important aspects of developing, deploying, and managing a NestJS application:",
  "date": "2024-07-12",
  "tags": [
    "Node.js"
  ],
  "readingTime": "3 min",
  "url": "https://medium.com/@mobinshaterian/best-practices-for-developing-deploying-and-managing-nestjs-applications-cef0edc4681f",
  "hero": "https://cdn-images-1.medium.com/max/800/1*t6MRccg0DYorLSbt5vt6_Q.jpeg",
  "content": [
    {
      "type": "paragraph",
      "html": "The document covers several important aspects of developing, deploying, and managing a NestJS application:"
    },
    {
      "type": "paragraph",
      "html": "1. Logging: Using the built-in Logger class for various logging levels.<br>2. Error tracking: Integrating Sentry for advanced error monitoring.<br>3. Environment variables: Using cross-env and <a href=\"http://twitter.com/nestjs/config\" target=\"_blank\" rel=\"noreferrer noopener\">@nestjs/config</a> for managing configurations.<br>4. Database configuration: Asynchronously reading environment variables for database setup.<br>5. Deployment: Steps for deploying to Heroku, including database setup and configuration.<br>6. CI/CD: Using GitHub Actions for continuous integration and deployment.<br>7. Frontend deployment: Brief mention of deploying the frontend to GitHub Pages."
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*t6MRccg0DYorLSbt5vt6_Q.jpeg",
      "alt": "Best Practices for Developing, Deploying, and Managing NestJS Applications",
      "caption": "",
      "width": 1024,
      "height": 1024
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Essay: Streamlining NestJS Application Development and Deployment"
    },
    {
      "type": "paragraph",
      "html": "NestJS has emerged as a powerful framework for building scalable and efficient server-side applications with Node.js. As applications grow in complexity, developers need robust tools and practices to manage, monitor, and deploy their projects effectively. This essay explores key aspects of NestJS application development and deployment, highlighting best practices and tools that can significantly improve the development workflow."
    },
    {
      "type": "paragraph",
      "html": "One of the fundamental aspects of maintaining a healthy application is proper logging. NestJS provides a built-in Logger class that allows developers to log messages at various levels of severity. By incorporating structured logging throughout the application, developers can gain valuable insights into application behavior, troubleshoot issues more effectively, and monitor performance in production environments."
    },
    {
      "type": "paragraph",
      "html": "For more advanced error tracking and monitoring, integrating a service like Sentry can provide real-time error reporting and detailed diagnostics. This allows developers to quickly identify and resolve issues in production, improving overall application reliability and user experience."
    },
    {
      "type": "paragraph",
      "html": "Managing application configurations across different environments is crucial for maintaining a flexible and secure deployment process. The <a href=\"http://twitter.com/nestjs/config\" target=\"_blank\" rel=\"noreferrer noopener\">@nestjs/config</a> package, combined with environment-specific&nbsp;.env files, offers a clean and efficient way to handle configuration variables. This approach allows developers to easily switch between development, staging, and production environments without hard-coding sensitive information."
    },
    {
      "type": "paragraph",
      "html": "When it comes to database configuration, NestJS’s modular architecture shines. By using TypeORM with asynchronous configuration, developers can dynamically set up database connections based on environment variables. This flexibility is particularly useful when deploying to different environments or cloud platforms."
    },
    {
      "type": "paragraph",
      "html": "Deploying a NestJS application to a cloud platform like Heroku involves several steps, from setting up a database to configuring environment variables. The document outlines a straightforward process for deploying to Heroku, including commands for creating a PostgreSQL database, setting environment variables, and pushing code to the Heroku repository. This deployment strategy provides a solid foundation for getting a NestJS application up and running in a production environment."
    },
    {
      "type": "paragraph",
      "html": "To further streamline the deployment process, incorporating continuous integration and deployment (CI/CD) practices using GitHub Actions can automate testing and deployment tasks. This approach ensures that code changes are automatically tested and deployed, reducing the likelihood of human error and increasing the speed of development iterations."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Add logger"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "main.ts"
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "const logger = new Logger();\nlogger.log(`Application listening on port 3000`);"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Define in controller"
    },
    {
      "type": "code",
      "lang": "javascript",
      "code": "export class TasksController {\n  private logger = new Logger('TasksController');"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Using in controller"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "this.logger.verbose(\n  `User \"${user.username}\" retrieving all tasks. Filters: ${JSON.stringify(filterDto)}`,\n);"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*j51eS8bcZx9-8dIkQ_JlfA.png",
      "alt": "Best Practices for Developing, Deploying, and Managing NestJS Applications",
      "caption": "",
      "width": 918,
      "height": 53
    },
    {
      "type": "paragraph",
      "html": "<strong>Using in repository</strong>"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "try {\n  const tasks = await query.getMany();\n  return tasks;\n} catch (error) {\n  this.logger.error(\n    `Failed to get tasks for user \"${user.username}\". Filters: ${JSON.stringify(filterDto)}`,\n    error.stack,\n  );\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Nest.js plus sentry"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Environment Variables"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "yarn global add cross-env"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "console.log(process.env);"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "npm_package_jest_testRegex: '.*\\\\.spec\\\\.ts$', npm_package_devDependencies_ts_node: '^10.9.1',\nnpm_package_devDependencies__types_supertest: '^6.0.0', npm_package_devDependencies__types_node:\n'^20.3.1', npm_package_dependencies__nestjs_platform_express: '^10.0.0',"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Add Configuration"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "yarn add @nestjs/config"
    },
    {
      "type": "paragraph",
      "html": "app.module.ts"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "ConfigModule.forRoot({      envFilePath: [`.env.stage.${process.env.STAGE}`],    }),"
    },
    {
      "type": "paragraph",
      "html": "add&nbsp;.env files"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*mRP4GQsGZx7A8J1nIpMz2g.png",
      "alt": "Best Practices for Developing, Deploying, and Managing NestJS Applications",
      "caption": "",
      "width": 266,
      "height": 47
    },
    {
      "type": "paragraph",
      "html": "package.json"
    },
    {
      "type": "code",
      "lang": "json",
      "code": "{\n  \"start:dev\": \"STAGE=dev nest start --watch\",\n  \"start:debug\": \"STAGE=dev nest start --debug --watch\",\n  \"start:prod\": \"STAGE=prod node dist/main\",\n  \"lint\": \"eslint \\\"{src,apps,libs,test}/**/*.ts\\\" --fix\",\n  \"test\": \"STAGE=dev jest\"\n}"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Use .env configuration in Controller"
    },
    {
      "type": "paragraph",
      "html": "controller"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "constructor(    private tasksService: TasksService,    private configService: ConfigService,  ) {\nconsole.log(configService.get('DATABASE_HOST'));  }"
    },
    {
      "type": "paragraph",
      "html": "tasks.module.ts"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "@Module({\n  imports: [ConfigModule, TypeOrmModule.forFeature([Task]), AuthModule], controllers:\n  [TasksController], providers: [TasksService, TaskRepository],\n})"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Async Read .env"
    },
    {
      "type": "paragraph",
      "html": "app.module.ts"
    },
    {
      "type": "code",
      "lang": "typescript",
      "code": "@Module({\n  imports: [ConfigModule.forRoot({\n    envFilePath: [`.env.stage.${process.env.STAGE}`],\n  }), // Add ConfigModule to the imports array ConfigModule, TypeOrmModule.forRootAsync({\n    imports: [ConfigModule], inject: [ConfigService], useFactory: async (configService:\n    ConfigService) => ({\n      type: 'postgres', host: configService.get('DB_HOST'), port:\n      parseInt(configService.get('DB_PORT')), username: configService.get('DB_USER'), password:\n      configService.get('DB_PASS'), database: configService.get('DB_DATABASE'), autoLoadEntities:\n      true, synchronize: false,\n    }),\n  }), TasksModule, AuthModule,],\n})"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Deployment"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Heroku command"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "yarn global add heroku"
    },
    {
      "type": "paragraph",
      "html": "<strong>Check heroku</strong>"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku -v"
    },
    {
      "type": "paragraph",
      "html": "<strong>Login heroku</strong>"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "keroku login"
    },
    {
      "type": "paragraph",
      "html": "<strong>Make Database</strong>"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku addons:create heroku-postgresql:hobby-dev -a name_application"
    },
    {
      "type": "paragraph",
      "html": "<strong>Add SSL connection</strong>"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*ZM5o4pjuZG8WAuRQnlDdvw.png",
      "alt": "Best Practices for Developing, Deploying, and Managing NestJS Applications",
      "caption": "",
      "width": 798,
      "height": 328
    },
    {
      "type": "paragraph",
      "html": "<strong>Push on heruko</strong>"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku git:remote -a name_application"
    },
    {
      "type": "paragraph",
      "html": "<strong>Configuration</strong>"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku config:set NPM_CONFIG_PRODUCTION=false"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku config:Set NODE_ENV=production"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku config:set DB_HOST=...heroku config:set DB_PORT=5432heroku config:set DB_USERNAME=...heroku\nconfig:set DB_PASSWORD=...heroku config:set DB_DATABASE=...heroku config:set JWT_SECRECT=..."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Add Procfile in root folder of project"
    },
    {
      "type": "image",
      "src": "https://cdn-images-1.medium.com/max/800/1*CaYnr86zemaSfyYADSxwFg.png",
      "alt": "Best Practices for Developing, Deploying, and Managing NestJS Applications",
      "caption": "",
      "width": 360,
      "height": 124
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Deploy"
    },
    {
      "type": "code",
      "lang": "bash",
      "code": "git push -f heroku HEAD:master"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Logs"
    },
    {
      "type": "code",
      "lang": "text",
      "code": "heroku logs --tail"
    },
    {
      "type": "heading",
      "level": 3,
      "text": "Github action"
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Deploying Your NestJS Application to a Cloud Server (AWS, Azure, Digital Ocean)with GitHub Actions — The Easy and Saving Cost Way."
    },
    {
      "type": "heading",
      "level": 2,
      "text": "Deploy front end on github"
    },
    {
      "type": "paragraph",
      "html": "<a href=\"https://github.com/arielweinberger/task-management-frontend/blob/master/.github/workflows/deploy.yml\" target=\"_blank\" rel=\"noreferrer noopener\">https://github.com/arielweinberger/task-management-frontend/blob/master/.github/workflows/deploy.yml</a>"
    }
  ]
}
