新坑 不一定填完
本次改造内容:
- 目录结构
- TSLint替换为ESLint
- pre-commit约束
- 环境变量
官方脚手架
1 2
| npm i -g @nestjs/cli nest new project-name
|
目录结构
nest的目录结构没有严格规定,以下是个人划分方法(src目录),
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| src |--extends // 业务无关模块或服务相关模块 |--config |--logger |--schedule |--providers // 贯穿从请求到返回的一系列东西 |--filter |--interceptor |--middleware |--guard |--pipe |--module // 业务模块 |--moduleA |--dto |--schemas |--interface |--moduleA.service.ts |--moduleA.controller.ts |--moduleA.module.ts |--utils // 工具 |--enums // 枚举 |--exceptions // 异常
|
TSLint替换为ESLint
为什么要替换?因为微软不打算搞了:https://medium.com/palantir/tslint-in-2019-1a144c2317a9
删除TSLint
首先删除package.json中关于lint的部分
devDependencies
: 删除tslint包
scripts
: 删除lint脚本
然后删除根目录下的tslint.json
安装及配置ESLint
1 2 3 4 5 6 7
| npm i eslint \ @typescript-eslint/parser \ @typescript-eslint/eslint-plugin \ prettier \ eslint-config-prettiereslint-plugin-prettier \ --save-dev
|
prettier
可以选择不要,个人习惯了,基本上每个项目都在用
然后在根目录下新建.eslintrc.js
和.prettierrc
(可选)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| module.exports = { parser: '@typescript-eslint/parser', extends: [ 'plugin:@typescript-eslint/recommended', 'plugin:prettier/recommended' ], plugins: ['@typescript-eslint'], rules: { '@typescript-eslint/member-delimiter-style': [ 'error', { multiline: { delimiter: 'none', requireLast: false }, singleline: { delimiter: 'comma', requireLast: false } } ] } }
{ "singleQuote": true, "semi": false }
|
根据需要可以自行添加规则
pre-commit约束
添加pre-commit的钩子,保证风格规范统一
npm i husky lint-staged --save-dev
1 2 3 4 5 6 7 8 9 10 11 12 13
| "husky": { "hooks": { "pre-commit": "lint-staged" } }, "lint-staged": { "src/**/*.{js,ts}": [ "prettier --write", "eslint --fix", "git add" ] }
|
环境变量
环境变量这块用的官方,使用env
文件+module的方式,
1 2
| npm i --save dotenv npm i --save-dev @types/dotenv
|
新建src/config/config.service.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import * as dotenv from 'dotenv' import * as fs from 'fs'
export class ConfigService { private readonly envConfig: { [key: string]: string }
constructor(filePath: string) { this.envConfig = dotenv.parse(fs.readFileSync(filePath)) }
get(key: string): string { return this.envConfig[key] } }
|
新建src/config/config.module.ts
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import { Module, Global } from '@nestjs/common' import { ConfigService } from './config.service'
@Global() @Module({ providers: [ { provide: ConfigService, useValue: new ConfigService(`${process.env.NODE_ENV}.env`) } ], exports: [ConfigService] }) export class ConfigModule {}
|
最后在app.module.ts
中注册
1 2 3 4 5 6 7
| import { Module } from '@nestjs/common' import { ConfigModule } from './config/config.module'
@Module({ imports: [ConfigModule] }) export class AppModule {}
|
使用
现在根目录下有个development.env
文件
安装cross-env
1
| npm i cross-env --save-dev
|
然后修改package.json
的scripts
1
| "start:dev": "cross-env NODE_ENV=development ..."
|
生产环境打算build之后用pm2,暂时不修改
由于ConfigModule
被包装成了全局模块,在AppModule
注册过就能在别的地方直接使用。
假设有个user.service.ts
1 2 3 4 5 6 7 8 9 10 11
| import { Injectable } from '@nestjs/common' import { ConfigService } from '../../config/config.service.ts'
export class UserService { constructor(private readonly configService: ConfigService) {}
async findOne(): Promise<string> { const user = this.configService.get('USER') return user } }
|
如果要在main.ts
中使用的话:
1 2 3 4 5 6 7 8 9 10 11 12
| import { NestFactory } from '@nestjs/core' import { AppModule } from './app.module' import { ConfigService } from './config/config.service'
async function bootstrap(): Promise<void> { const app = await NestFactory.create(AppModule) const configService = app.get(ConfigService) const port = configService.get('PORT')
await app.listen(port) } bootstrap()
|
当然这是最简单的环境变量设置方法,如果需要智能提示、类型、校验等功能,官方有结合Joi的方法。