欢迎订阅Nest.js口袋书专栏
如果您觉得这篇文章有帮助的话!给个点赞和评论支持下吧,感谢~
作者:前端小王hs
阿里云社区博客专家/清华大学出版社签约作者✍/者作问访万百NDSC/B站千粉前端up主
人生若只如初见
基础结构
当使用nest new project-name
这个由Nest CLI
提供的命令后,会在当前目录下新建一个名由自定义的project-name
的目录,里面的文件结构如下图所示:

下面,让我们一起(由上到下)分析根目录内的文件(夹)
node_modules
当通过npm
、yarn
或pnpm
这些包管理器安装依赖项时,会自动生成此文件用于存放项目所使用的依赖文件
src
项目的核心目录,关于这一点,我们会在第4节核心目录进行介绍
test
用于存放测试文件的目录,这也是nest
与其他框架不同的一点,即鼓励开发者编写测试逻辑。在后续的实战中,我们也会在nest
中进行测试,保证代码的质量和可维护性
.eslintrc.js
通过名字我们可以知道这是与ESLint
相关的文件,ESLint
是一个开源的JavaScript
代码检查工具,主要用于代码的规范,由此可见nest
对代码的要求性。
而当前文件正是ESLint
的配置文件,允许我们自定义ESLint
的行为,下面我们来看下里面的代码:
js
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
sourceType: 'module',
},
plugins: ['@typescript-eslint/eslint-plugin'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
root: true,
env: {
node: true,
jest: true,
},
ignorePatterns: ['.eslintrc.js'],
rules: {
'@typescript-eslint/interface-name-prefix': 'off',
'@typescript-eslint/explicit-function-return-type': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'off',
},
};
由于注释较长,所以笔者将代码所表达或实现的内容写在下面:
(1)parser
:意为解析,在代码中使用了@typescript-eslint/parser
,用于ESLint
解析TypeScript
代码
(2)parserOptions
:project
指定了TypeScript
的配置文件,也就是根目录中的tsconfig.json
;tsconfigRootDir
是指TypeScript
的配置文件在哪个目录,这里是__dirname
,也就是当前目录 ;sourceType
则是告诉ESLint
源代码类型是模块 ,这里指的是使用了ES6
的module
特性,如果是使用的Node.js
默认的CommonJS
,则无需添加sourceType
(3)plugins
:即插件 ,这里使用了@typescript-eslint/eslint-plugin
,这个插件设计了很多针对TypeScript
的ESLint
规则
(4)extends
:使用已经存在 的规则,与之相对的是需要开发者自定义的规则。在文件中是使用了@typescript-eslint
和 prettier
推荐的规则
(5)root
:意为"根",就是标记当前目录为ESLint
的根目录
(6)env
:使用的全局变量和环境。在文件中启用了node
和jest
的全局变量和环境,一个简单的例子就是在(2)中的__dirname
,它就是Node.js
特有的一个全局变量
(7)ignorePatterns
:ignore意为忽略,其实就是忽略对某个文件的检查,在文件中就是忽略对自身的检查
(8)rules
:默认定义的自定义 ESLint
规则,可以看到都是false
。
第一个是interface-name-prefix
,在一些严格的项目中,要求interface
的名字前缀具有某些规则,这里取消了这个要求
第二个是explicit-function-return-type
,要求函数是否有显式的返回类型,这里为false
,这其实非常宽松
第三个是explicit-module-boundary-types
,要求模块导出时是否具有显式的类型,这里为false
第四个是是否禁止使用显式的any
类型,也就是是否要禁止出现anyScript 这种情况,这里为false
可以看到这些规则还是保留了开发时的宽松风格,这里不得不提的就是很多初级开发者 对ESLint
较为反感,在使用脚手架 搭建项目时都不添加ESLint
。从长期看,这对自己的开发生涯并不十分有利,所以笔者还是建议养成良好的代码风格,不管是进入大厂 ,又或当自己有朝一日成为项目总监时,都是十分有好处的
.gitignore
看名字就知道,这是一个与git
相关的文件,没错!这个文件主要是用于设定将代码上传至远程仓库时,哪些文件是无需上传的
举个简单的例子,我们知道node_modules
由于存放的都是项目依赖,所以导致该文件目录十分大,也因为如此,该文件通常不会上传至远程仓库,那么就可以在.gitignore
中添加node_modules
。事实上,该文件通常都会带上node_modules
,即使是由脚手架自动生成的

那么问题来了,读者知道上图中的/dist
和/build
是什么用途的文件吗?
.prettierrc
Prettier
是一个代码格式化的工具,而该文件就是配置文件。代码非常简单,如下所示:
js
{
"singleQuote": true,
"trailingComma": "all"
}
singleQuote
是说代码中的字符串应该由单引号 包裹而不是双引号,代码如下:
ts
const name = '前端小王hs'
而trailingComma
是指数组或对象的最后一个元素是否还要添加逗号,代码如下:
ts
const obj = {
name:'前端小王hs',
age:24,
}
nest-cli.json
这是Nest CLI
的配置文件,这里我们主要注意后两个属性,即sourceRoot
和compilerOptions
,前者主要是定义了项目的根目录,当执行打包等命令时,nest
会从该属性值去执行命令,在文件中即为根目录src
;compilerOptions
则是可以自定义编译选项,这里的deleteOutDir
为true
是指编译前删除输出目录 ,这里的输出目录 即我们之前提到的dist,那么您猜对答案了吗!
package.json
这是Node.js
的核心文件,那么在里面包括了项目的名称、版本、描述、入口文件、使用的依赖等,其实就是我们在使用npm init
命令时输入的内容
pnpm-lock.yaml
保存了依赖的锁定版本信息
笔者注:在笔者的新书 中将会对npm
、yarn
和pnpm
三个包管理器的出现、常规命令、优缺点进行了详细的介绍,那么就包括了为什么需要进行锁定版本 的内容介绍,对书 感兴趣的朋友可以关注笔者获取第一时间的出版讯息
README.md
这是一个Markdown 格式的文档,通常用于介绍项目的架构 、功能 、启动命令 、开源协议等内容
tsconfig.build.json
这是一个TypeScript
的配置文件,主要是用于拓展或覆盖默认的tsconfig.json
文件,例如在不同的环境下,可能需要不同的TS
配置,就可以在该文件中对原有配置进行覆盖 或者说修改
我们直接看代码
json
{
"extends": "./tsconfig.json",
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}
第一个属性extends
其实就是说使用了默认的tsconfig.json
文件;第二个属性则排除了无需编译的文件
tsconfig.json
TypeScript
的主要配置文件,我们主要从默认的配置项中进行分析,代码如下:
json
"compilerOptions": {
// 使用CommonJS的模块体系
"module": "commonjs",
// 生成.d.ts声明文件
"declaration": true,
// 生成JS文件时移除所有注释
"removeComments": true,
// 为装饰器提供元数据支持
"emitDecoratorMetadata": true,
// 提供对装饰器的实验性支持
"experimentalDecorators": true,
// 允许在没有默认导出的模块中默认导入
"allowSyntheticDefaultImports": true,
// 代码符合ES2021规范
"target": "ES2021",
// 生成源映射文件.map
"sourceMap": true,
// 编译后的输出目录
"outDir": "./dist",
// 用于解析时的基准目录
"baseUrl": "./",
// 增量编译
"incremental": true,
// 跳过所有声明文件的类型检查
"skipLibCheck": true,
// 不启用严格Null检查
"strictNullChecks": false,
// 不会隐式添加any类型
"noImplicitAny": false,
// 不启用bind/call/apply的严格检查
"strictBindCallApply": false,
// 不强调在文件引用中使用一致性的大小写
"forceConsistentCasingInFileNames": false,
// 假设switch中存在case但没有break,不报错
"noFallthroughCasesInSwitch": false
}
对于TypeScript
的更多配置内容,读者可通过学习TypeScript
进行了解,笔者在这里就不过的叙述了,如果在后续的代码实战中有需要,读者会对使用的TypeScript
进行介绍
本篇最后
码字不易,这一过程涉及到如何将晦涩的概念以通俗的言语表达出来,如果感觉这篇文章对您有帮助,笔者希望能得到您的评论+关注 !您的评论+关注是我更文的最大动力!
如果您发现有错字,还请见谅并给予指正建议,笔者会在最短时间内修改并私聊感谢!
如果由于不可抗拒因素导致拖更,还请您见谅!
如果需进一步技术交流,请您在首页联系方式内联系我!