这是我参与「第五届青训营 」伴学笔记创作活动的第 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 仓库查看。