NestJS 环境搭建(一)| 青训营笔记

288 阅读1分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天。我们 Bocchi 小组采用 NestJS 开发这次掘金站点的后端,这几天我尝试搭建了一下后端基础环境,因此这篇文章来记录下 NestJS 的基础环境配置。

仓库地址: github.com/Bocchi-Deve…

打包

如果直接使用 NestJS 自带的打包方式,那么打包出来的文件会依赖臃肿的 node_modules无法单独部署且打包成 docker 镜像也很不方便,这是我们不想要的结果。

这里我们可以采用由 vercel 编写的 ncc 来进行打包,他可以把我们的代码以及 node_modules 相关依赖全部打包到一个 index.js 文件里面。

pnpm i @vercel/ncc -d

修改 package.json

  "scripts": {
		...
    "build": "nest build",
    "bundle": "rimraf out && npm run build && cd dist/src && npx ncc build main.js -o ../../out -m -t && cd ../.. && chmod +x out/index.js",
  },

之后输入 pnpm bundle 即可打包。

swagger、跨域、日志

这里展示下我们小组 swagger、跨域、日志等相关配置

import { Logger, ValidationPipe } from '@nestjs/common'
import { NestFactory } from '@nestjs/core'

import { API_VERSION, CROSS_DOMAIN, PORT } from './app.config'
import { AppModule } from './app.module'
import { LoggingInterceptor } from './common/interceptors/logging.interceptor'
import { isDev } from './global/env.global'

declare const module: any

export async function bootstrap() {
  const app = await NestFactory.create(AppModule)
  const logger = new Logger()
  const hosts = CROSS_DOMAIN.allowedOrigins.map((host) => new RegExp(host, 'i'))
  app.enableCors(
    hosts
      ? {
          origin: (origin, callback) => {
            const allow = hosts.some((host) => host.test(origin))

            callback(null, allow)
          },
          credentials: true,
        }
      : undefined,
  )

  app.setGlobalPrefix(isDev ? '' : `api/v${API_VERSION}`)
  if (isDev) {
    app.useGlobalInterceptors(new LoggingInterceptor())
  }

  app.useGlobalPipes(
    new ValidationPipe({
      transform: true,
      whitelist: true,
      errorHttpStatusCode: 422,
      forbidUnknownValues: true,
      enableDebugMessages: isDev,
      stopAtFirstError: true,
    }),
  )

  if (isDev) {
    const { DocumentBuilder, SwaggerModule } = await import('@nestjs/swagger')
    const options = new DocumentBuilder()
      .setTitle('API')
      .setDescription('JueJin API')
      .setVersion(`${API_VERSION}`)
      .addSecurity('bearer', {
        type: 'http',
        scheme: 'bearer',
      })
      .addBearerAuth()
      .build()
    const document = SwaggerModule.createDocument(app, options)
    SwaggerModule.setup('api-docs', app, document)
  }

  await app.listen(+PORT, '0.0.0.0', async () => {
    if (isDev) {
      logger.debug(`Server listen on:: http://localhost:${PORT}`)
      logger.debug(`swagger文档: http://localhost:${PORT}/api-docs`)
    }
  })

  if (module.hot) {
    module.hot.accept()
    module.hot.dispose(() => app.close())
  }
}

import { argv } from 'zx-cjs'

export const PORT = 7498
export const API_VERSION = 1

export const CROSS_DOMAIN = {
  allowedOrigins: ['suemor.com', 'localhost', '127.0.0.1', '.*dev'],
}

export const MONGO_DB = {
  dbName: 'juejin',
  // 读取 docker 配置
  host: argv.db_host || '127.0.0.1',
  port: 27017,
  get uri() {
    return `mongodb://${this.host}:${this.port}/${this.dbName}`
  },
}

export const AXIOS_CONFIG = {
  timeout: 10000,
}

export const SECURITY = {
  jwtSecret: 'juejin',
  jwtExpire: '7d',
}

async function main() {
  const [{bootstrap}] = await Promise.all([
    import('./bootstrap'),
    import('./app.config')
  ])

  bootstrap()
}

main()

具体代码可以去开头 github 仓库查看。