Node 核心基础学习计划

版本:v2.0
日期:2026-06-15
目标:从零搭建 Node 工程,掌握模块系统、异步处理、环境变量,最终完成 Nest 项目初始化
预计周期:8 天(每天投入 1.5 ~ 2 小时)
前置条件:已安装 Node.js >= 18.x,有基本 JavaScript 基础


一、学习路线总览

阶段 日期 主题 核心产出
Day 1-2 06/16 - 06/17 包管理与模块系统 能独立搭建 Node 项目,熟练使用 pnpm,理解 ESM/CJS 差异
Day 3-4 06/18 - 06/19 核心内置模块与异步 能用 fs/path 操作文件,async/await 处理异常,写出健壮的工具函数
Day 5-6 06/20 - 06/21 HTTP 原生服务 能手写极简 HTTP 服务器,理解请求/响应生命周期
Day 7-8 06/22 - 06/23 Nest.js 工程化 能用 Nest CLI 创建项目,理解分层架构,跑通第一个 CRUD

二、阶段一:包管理与模块系统(Day 1-2)

2.1 切入角度

从"一个 Node 项目从 0 到 1 是怎么搭出来的"这个问题出发,串联包管理器、模块规范和项目配置三个核心概念。不要孤立地学语法,而是以搭建一个真实项目为线索,把知识点串起来。

2.2 具体学习点

pnpm 包管理器
  • 安装与全局配置:通过 npm install -g pnpm 安装,执行 pnpm --version 验证;理解 pnpm 相比 npm/yarn 的核心优势——硬链接 + 符号链接节省磁盘空间、严格的依赖隔离(不能偷偷引用间接依赖)、更快的安装速度
  • 常用命令对照:pnpm init(初始化项目)、pnpm add <pkg>(安装生产依赖)、pnpm add -D <pkg>(安装开发依赖)、pnpm remove <pkg>(移除依赖)、pnpm install(根据 lock 文件安装所有依赖)、pnpm run <script>(执行 package.json 中定义的脚本)
  • pnpm 与 npm 的行为差异:pnpm 默认不扁平化 node_modules(非 hoisted),这意味着你不能引用未声明的间接依赖——这是一个常见的踩坑点。比如你安装了 express 但没有安装它的子依赖 body-parser,在 pnpm 中直接 require('body-parser') 会报错
  • workspace 概念(了解即可):pnpm-workspace.yaml 用于 monorepo 多包管理,知道有这个东西即可,暂不深入实践
ESM 与 CommonJS 模块系统
  • CommonJS(CJS)基础:Node 的传统模块规范,使用 require() 导入、module.exports 导出;理解 require 的同步加载机制和缓存策略(同一模块只执行一次,后续 require 走缓存)
  • ESM(ECMAScript Modules)基础:使用 import/export 语法;理解静态分析特性——编译期就能确定依赖关系,支持 Tree-shaking 优化
  • 如何切换模块类型:package.json 中设置 "type": "module" 使 .js 文件按 ESM 解析;不设或设为 "commonjs" 则按 CJS 解析;.mjs 文件强制 ESM,.cjs 文件强制 CJS
  • CJS 与 ESM 互操作:CJS 中用 require() 可以导入 ESM 的默认导出(Node 14+ 有限支持);ESM 中用 import 可以导入 CJS(module.exports 变成默认导出);实际项目中尽量统一用一种,避免混用带来的心智负担
  • __dirname / __filename 在 ESM 中的替代方案:ESM 没有这两个全局变量,需要通过以下方式手动构造:

import { fileURLToPath } from 'url'
import { dirname } from 'path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
package.json 核心字段
  • 基础字段:name(包名,npm 发布时需唯一)、version(语义化版本号 major.minor.patch)、description(项目描述)、author(作者)
  • 入口与类型:main(CJS 入口文件)、module(ESM 入口,部分打包工具识别)、type(模块类型:"commonjs" 或 "module")、exports(条件导出,现代 Node 推荐的用法,支持按环境/模块类型指定不同入口)
  • 脚本(scripts):定义可执行命令,如 "dev": "node --watch src/index.js"(Node 18+ 内置热重载)、"build": "tsc"、"start": "node dist/index.js"、"test": "vitest"
  • 依赖分类:dependencies(生产环境依赖,运行时必须的包)、devDependencies(开发依赖,如 TypeScript、ESLint、测试框架)、peerDependencies(对等依赖,插件场景常用,声明"我需要宿主安装某版本的包")
  • engines 字段:声明 Node 版本要求,如 "engines": { "node": ">=18.0.0" },团队协作和 CI/CD 中很有用
环境变量配置
  • process.env 基础:Node 通过 process.env 对象读取系统环境变量,所有值都是字符串类型;process.env.NODE_ENV 是最常用的变量,用来区分开发环境(development)和生产环境(production)
  • .env 文件 + dotenv 库:创建 .env 文件写入键值对(如 PORT=3000、DB_HOST=localhost),安装 dotenv 并在入口文件顶部执行 import 'dotenv/config' 自动加载;.env 文件必须加入 .gitignore,不能提交到 Git 仓库
  • Node 20+ 原生 .env 支持:node --env-file=.env src/index.js 可以原生加载 .env 文件,无需 dotenv;了解即可,项目中仍建议用 dotenv 保证向下兼容性
  • 多环境配置文件约定:.env.development(开发环境)、.env.production(生产环境)、.env.local(本地覆盖,不提交 Git);Nest 框架后续会用 @nestjs/config 模块统一管理

2.3 达成效果

  • 能用 pnpm init + pnpm add 从零搭建一个 Node 项目,正确配置 package.json
  • 能清晰解释 require 与 import 的区别,并在项目中统一使用一种模块规范
  • 能用 .env + dotenv 管理环境变量,理解不同环境的配置切换逻辑
  • 能解释 pnpm install 和 npm install 在 node_modules 结构上的核心差异

2.4 练习任务

项目:创建一个 node-module-demo 项目
├── package.json(配置 type: "module",定义 dev/start 脚本)
├── .env(配置 PORT=3000、APP_NAME=demo)
├── .gitignore(排除 node_modules 和 .env)
├── src/
│   ├── index.js(ESM 入口,导入并调用 utils 和 config)
│   ├── utils.js(导出一个 formatDate 函数)
│   └── config.js(读取 .env 中的变量并导出配置对象)

三、阶段二:核心内置模块与异步处理(Day 3-4)

3.1 切入角度

以"写一个文件管理小工具"为目标,在实践中掌握 Node 最常用的内置模块。重点理解异步编程在 Node 中的特殊性——几乎所有 I/O 操作都是异步的,这是 Node 区别于传统后端语言的核心特征。跳过 stream 相关内容,在实际项目中用到时再查文档即可。

3.2 具体学习点

path 模块(路径处理)
  • 核心方法
    • path.join() —— 拼接路径,自动处理平台分隔符
    • path.resolve() —— 解析为绝对路径(从右向左拼接,遇到绝对路径就重置)
    • path.extname() —— 获取文件扩展名(如 .json)
    • path.basename() —— 获取文件名(可传入 ext 参数去掉扩展名)
    • path.dirname() —— 获取目录路径
    • path.parse() —— 完整解析为对象 { root, dir, base, ext, name }
  • 为什么用 path 而非字符串拼接:Windows 用 \、Linux/Mac 用 /,path.join('a', 'b') 自动适配平台返回 a\b 或 a/b,手写 'a/' + 'b' 会跨平台出错
  • __dirname 与 process.cwd() 的区别:__dirname 是当前文件所在目录(CJS 全局变量),process.cwd() 是 Node 进程启动的工作目录。两者可能不同——比如你在 /home/user 下执行 node project/src/index.js,process.cwd() 是 /home/user,而 __dirname 是 /home/user/project/src。拼接文件路径时优先基于 __dirname(或 ESM 等价写法)
fs 模块(文件系统操作)
  • Promise API(重点掌握):使用 import fs from 'fs/promises',所有方法返回 Promise,可直接配合 async/await。这是现代 Node 开发的推荐方式
  • 常用操作
    • 读文件:await fs.readFile(path, 'utf-8') —— 注意不传编码会返回 Buffer 对象而非字符串
    • 写文件:await fs.writeFile(path, content) 覆盖写入;await fs.appendFile(path, content) 追加写入
    • 目录操作:await fs.mkdir(dir, { recursive: true }) 递归创建目录、await fs.readdir(dir) 列出目录内容、await fs.rm(path, { recursive: true, force: true }) 递归删除
    • 文件信息:await fs.stat(path) 返回 Stats 对象,包含 .isFile()、.isDirectory()、.size(字节)、.mtime(修改时间)等
    • 判断存在:await fs.access(path) 不报错即存在(不要用 fs.exists,已废弃,且存在竞态条件问题)
    • 复制/移动/重命名:await fs.copyFile(src, dest)、await fs.rename(oldPath, newPath)
  • 回调式 API(了解):fs.readFile(path, (err, data) => { ... }) 是传统写法,了解其错误优先的回调约定即可,实际项目全部用 Promise API
  • 同步 API(了解):fs.readFileSync() 等阻塞式方法会卡住整个事件循环,仅在启动脚本或 CLI 工具中偶尔使用,业务代码禁止使用
async/await 与异常处理
  • async/await 本质:async 函数自动返回 Promise,await 暂停执行等待 Promise 解决;本质是 Promise.then() 链的语法糖,但可读性大幅提升,避免了"回调地狱"
  • try/catch 异常捕获:每个 await 调用都应该有对应的错误处理,要么局部 try/catch,要么在外层统一捕获。未捕获的 Promise rejection 在 Node 中会导致进程崩溃(触发 unhandledRejection 事件,未来版本将直接退出进程)
  • 错误处理最佳实践
    • 不要吞掉错误:try { ... } catch(e) {} 这种写法极其危险,至少 console.error(e) 记录日志
    • 区分两类错误:可预期错误(文件不存在、网络超时、参数校验失败)应该业务处理;不可预期错误(程序 bug、内存溢出)应该记录日志后让进程退出并重启
    • 封装统一工具:写一个 safeAsync(fn) 工具函数,避免到处写 try/catch:

async function safeAsync(promise) {
  try {
    const data = await promise
    return [null, data]
  } catch (err) {
    return [err, null]
  }
}

// 使用方式
const [err, data] = await safeAsync(fs.readFile('config.json', 'utf-8'))
if (err) {
  console.error('读取配置文件失败:', err.message)
  process.exit(1)
}
console.log('配置加载成功:', data)
  • Promise 并发控制
    • Promise.all([p1, p2, p3]) —— 全部成功才成功,任一失败即失败。适合无依赖关系的并行任务(如同时读取多个文件)
    • Promise.allSettled([p1, p2]) —— 等所有 Promise 完成,不论成败,返回每个任务的状态和结果。适合需要知道每个任务结果的场景
    • Promise.race([p1, p2]) —— 谁先完成就用谁的结果。适合实现超时控制(将业务 Promise 与 setTimeout Promise 竞赛)
  • process 错误事件(了解):process.on('uncaughtException', ...) 捕获未处理的同步异常、process.on('unhandledRejection', ...) 捕获未处理的 Promise 拒绝。生产环境中用这两个事件记录日志后优雅退出

3.3 达成效果

  • 能用 fs/promises 完成所有常见文件操作(读写、创建目录、遍历、判断文件类型)
  • 能用 path 模块写出跨平台兼容的路径处理代码
  • 能在异步代码中正确使用 try/catch,区分可预期和不可预期错误
  • 能用 Promise.all 等 API 实现异步任务的并行执行
  • 能写出一个包含文件遍历、批量处理、错误兜底的实用脚本

3.4 练习任务

项目:创建一个 file-toolkit 命令行工具
├── src/
│   ├── index.js(入口,调用各功能函数)
│   ├── fileUtils.js(封装:读取 JSON 文件、遍历目录、批量重命名)
│   └── asyncDemo.js(演示:Promise.all 并行读取 + 统一错误处理)
功能要求:
  1. 读取指定目录下所有 .json 文件,解析并合并内容
  2. 对读取过程中的每个错误进行 try/catch 并输出日志
  3. 用 Promise.all 并行读取多个文件,统计总耗时
  4. 实现 safeAsync 工具函数并用它处理文件读取

四、阶段三:HTTP 原生极简服务(Day 5-6)

4.1 切入角度

从"一个 HTTP 请求从浏览器发出到收到响应,Node 服务端到底发生了什么"这个问题出发。先用原生 http 模块手写最简服务器,建立对请求/响应模型的直觉理解。不学 Koa/Express 等框架,目的是先理解底层原理——后面学 Nest 时,你才能理解框架帮你封装了什么、省掉了哪些手动操作。

4.2 具体学习点

http 模块基础
  • 创建服务器

import http from 'http'

const server = http.createServer((req, res) => {
  // req = IncomingMessage(请求对象)
  // res = ServerResponse(响应对象)
  res.writeHead(200, { 'Content-Type': 'text/plain' })
  res.end('Hello World')
})

server.listen(3000, () => {
  console.log('Server running on http://localhost:3000')
})

每次有客户端请求到达,都会触发回调函数。

  • 请求对象 req 核心属性
    • req.method —— 请求方法字符串('GET'、'POST'、'PUT'、'DELETE')
    • req.url —— 请求路径(含 query string,如 /api/users?page=1&size=10)
    • req.headers —— 请求头对象(key 全部为小写,如 req.headers['content-type']、req.headers['authorization'])
    • 读取请求体(POST/PUT 等有 body 的请求):需要监听 data 和 end 事件拼接 Buffer:

let body = ''
req.on('data', chunk => { body += chunk.toString() })
req.on('end', () => {
  const data = JSON.parse(body)
  // 处理 data ...
})
  • 响应对象 res 核心方法

    • res.writeHead(statusCode, headers) —— 设置状态码和响应头(必须在 res.write/end 之前调用)
    • res.write(data) —— 写入响应体数据(可多次调用)
    • res.end(data) —— 结束响应(必须调用,否则客户端会一直等待)
    • 快捷写法:res.end(JSON.stringify({ success: true, data: [] })) 一步完成
  • Content-Type 处理

    • 返回 JSON:{ 'Content-Type': 'application/json; charset=utf-8' }
    • 返回 HTML:{ 'Content-Type': 'text/html; charset=utf-8' }
    • 返回纯文本:{ 'Content-Type': 'text/plain; charset=utf-8' }
请求/响应生命周期
  • 一个请求的完整流程:客户端发起请求 → TCP 连接建立(三次握手) → Node 接收请求触发回调 → 解析 URL/方法/请求头 → 读取请求体 → 业务逻辑处理 → 设置响应状态码和头 → 写入响应体 → end() 结束响应 → TCP 连接复用(keep-alive)或关闭
  • 路由的原始实现:没有框架时,路由就是 if/else 或 switch 判断 req.method + req.url。理解这一点非常重要——Express/Koa 的路由机制本质上就是对这个过程的封装,Nest 的装饰器路由则是更高级的抽象
  • Query String 解析:使用 new URL(req.url, 'http://localhost') 构造 URL 对象,然后通过 .searchParams.get('key') 提取查询参数
  • JSON 请求体解析:监听 data 事件拼接 Buffer,end 事件触发后 JSON.parse(body.toString()) 解析
实战要点
  • CORS 跨域处理:手动设置三个响应头——Access-Control-Allow-Origin: *(或指定域名)、Access-Control-Allow-Methods: GET,POST,PUT,DELETE、Access-Control-Allow-Headers: Content-Type,Authorization;对 OPTIONS 预检请求直接返回 204
  • 静态文件服务(了解原理):本质就是用 fs.readFile 读取文件 + res.end() 返回内容,根据文件扩展名设置对应的 Content-Type。理解这一点后你就知道 Nginx 等静态文件服务器在做什么了
  • 错误边界处理:用 try/catch 包裹每个路由的处理逻辑,未捕获的错误统一返回 500 状态码 + 错误信息 JSON;不存在的路由返回 404

4.3 达成效果

  • 能用原生 http 模块手写一个支持 GET/POST 的 RESTful 风格 API 服务器
  • 能手动解析 URL 路径、查询参数、JSON 请求体
  • 能解释从请求进入到响应发出的完整生命周期
  • 能理解 Express/Koa/Nest 等框架的路由、中间件机制本质上在封装什么

4.4 练习任务

项目:创建一个 mini-http-server
├── src/
│   ├── server.js(入口,创建服务器 + 路由分发)
│   ├── router.js(封装简易路由映射:method + path → handler)
│   ├── handlers/
│   │   ├── users.js(GET /users 返回列表,POST /users 创建用户)
│   │   └── health.js(GET /health 返回服务状态)
│   └── utils.js(封装:parseBody、setCorsHeaders、sendJson 响应)
功能要求:
  1. GET /users 返回 JSON 用户数组
  2. POST /users 接收 JSON body 并返回创建的用户
  3. GET /health 返回 { status: 'ok', uptime: process.uptime() }
  4. 未知路由返回 404 JSON
  5. 所有响应自动添加 CORS 头
  6. 服务端错误返回 500 并记录日志

五、阶段四:Nest.js 工程化(Day 7-8)

5.1 切入角度

从"为什么企业级 Node 项目需要框架"这个疑问出发。前面手写 HTTP 服务器时你一定感受到了:路由多了很难维护、错误处理到处重复、没有统一的项目结构规范、依赖关系全靠手动管理。Nest 就是来解决这些问题的。学习重点是理解 Nest 的分层架构和核心概念,而非穷举所有装饰器——装饰器用到时查文档即可。

5.2 具体学习点

Nest 环境搭建与 CLI
  • 安装 CLI:pnpm add -g @nestjs/cli,执行 nest --version 验证安装成功
  • 创建项目:nest new my-project —— CLI 交互式询问包管理器(选 pnpm),自动生成完整项目骨架并安装依赖
  • CLI 常用生成命令
    • nest generate module users —— 生成模块,自动注册到 AppModule
    • nest generate controller users —— 生成控制器
    • nest generate service users —— 生成服务(Provider)
    • nest g mo/co/sv users —— 缩写形式(mo=module、co=controller、sv=service)
    • nest generate resource products —— 推荐,一步生成完整 CRUD 模块(module + controller + service + DTO + 测试文件)
  • 启动与开发
    • pnpm run start:dev —— 热重载开发模式(文件修改自动重启)
    • pnpm run build —— TypeScript 编译为 JavaScript
    • pnpm run start:prod —— 生产模式启动(运行编译后的代码)
目录结构理解

my-project/
├── src/
│   ├── main.ts              # 应用入口:创建 Nest 实例、配置全局管道/中间件、监听端口
│   ├── app.module.ts        # 根模块:组织所有功能模块的入口
│   ├── app.controller.ts    # 根控制器(通常只放健康检查接口)
│   ├── app.service.ts       # 根服务
│   └── users/               # 功能模块目录(一个业务域一个目录)
│       ├── users.module.ts      # 模块声明:注册本模块的 controller 和 provider
│       ├── users.controller.ts  # 控制器:定义路由、接收请求、参数校验
│       ├── users.service.ts     # 服务层:封装业务逻辑、数据操作
│       └── dto/                 # 数据传输对象(定义请求参数结构)
│           ├── create-user.dto.ts
│           └── update-user.dto.ts
├── test/                    # 测试目录(单元测试 + e2e 测试)
├── nest-cli.json            # Nest CLI 配置文件
├── tsconfig.json            # TypeScript 编译配置
├── package.json
└── .env                     # 环境变量(不要提交到 Git)
  • 核心分层架构:Controller(接收请求、参数校验) → Service(业务逻辑处理) → Repository/数据源(数据库操作)。每一层只关心自己的职责,层与层之间通过依赖注入连接。这个分层模式和 Java 的 Spring 框架非常相似
  • Module 的作用:Nest 的核心组织单元。每个功能域一个 Module(如 UsersModule、ProductsModule)。Module 通过 imports 数组引入其他模块,通过 exports 数组暴露自己的 Service 给其他模块使用。没有 export 的 Service 只能在本模块内部使用
  • main.ts 做了什么:NestFactory.create(AppModule) 创建应用实例 → 配置全局中间件(CORS)→ 配置全局管道(ValidationPipe 参数校验)→ app.listen(3000) 启动监听
核心概念速览
  • 装饰器(Decorators):Nest 大量使用 TypeScript 装饰器来声明路由和参数映射关系:
    • @Controller('/users') —— 定义控制器的路由前缀
    • @Get()、@Post()、@Put()、@Delete() —— 定义 HTTP 方法和具体路径
    • @Body() —— 提取请求体
    • @Param('id') —— 提取路径参数(如 /users/:id 中的 id)
    • @Query('page') —— 提取查询参数
  • 依赖注入(DI):在 Controller 构造函数中声明 constructor(private readonly usersService: UsersService) {},Nest 的 IoC 容器会自动创建并注入 Service 实例。你不需要手动 new UsersService(),这是 Nest 的核心设计模式
  • DTO(数据传输对象):用 TypeScript class 定义请求参数的结构和校验规则,配合 class-validator 库的装饰器(@IsString()、@IsEmail()、@MinLength(6) 等)实现自动参数校验
  • 全局管道:在 main.ts 中配置 app.useGlobalPipes(new ValidationPipe({ transform: true, whitelist: true })),开启自动校验(whitelist 过滤掉 DTO 中未定义的字段,transform 自动类型转换)

5.3 达成效果

  • 能用 Nest CLI 创建项目并理解每个自动生成文件的用途
  • 能解释 Module / Controller / Service 三层各自的职责和关系
  • 能用 nest generate resource 快速生成一个完整的 CRUD 模块
  • 能配置全局 ValidationPipe 实现请求参数的自动校验
  • 能跑通一个完整的「创建用户 → 查询用户列表 → 更新 → 删除」API 流程
  • 能理解 Nest 的依赖注入机制,知道 IoC 容器在背后做了什么

5.4 练习任务

项目:创建一个 nest-demo 项目
功能要求:
  1. 使用 nest new 创建项目,选择 pnpm
  2. 用 nest generate resource users 生成 CRUD 模块
  3. 实现以下接口:
     - POST   /users(创建用户,带 DTO 校验:name 必填、email 格式校验)
     - GET    /users(获取用户列表)
     - GET    /users/:id(获取单个用户,不存在返回 404)
     - PUT    /users/:id(更新用户)
     - DELETE /users/:id(删除用户)
  4. 在 main.ts 中配置全局 ValidationPipe
  5. 配置 CORS 允许跨域
  6. 使用 .env 配置端口号,通过 @nestjs/config 读取
  7. 数据先用内存数组存储,后续可替换为数据库

六、每日学习检查清单

Day 1(06/16)— pnpm 与 package.json

  •  安装 pnpm 并验证版本(pnpm --version)
  •  执行 pnpm init 创建项目,生成 package.json
  •  安装 3 个生产依赖 + 2 个开发依赖,观察 lock 文件变化
  •  配置 package.json 的 scripts 字段,pnpm run dev 能启动
  •  理解 dependencies vs devDependencies 的区别(什么时候放哪个)
  •  配置 .env + dotenv,在代码中通过 process.env 读取环境变量

Day 2(06/17)— ESM 与 CommonJS

  •  创建一个 CJS 项目(默认),用 require/module.exports 写两个互相导入的模块
  •  切换到 ESM("type": "module"),用 import/export 重写同样的模块
  •  在 ESM 中实现 __dirname 的等价写法(import.meta.url + fileURLToPath)
  •  尝试 CJS 和 ESM 混用,观察报错信息,理解互操作的限制
  •  完成阶段一练习任务(node-module-demo 项目)

Day 3(06/18)— path 与 fs 模块

  •  用 path.join/resolve/extname/basename/dirname/parse 处理 5 种以上路径场景
  •  用 fs/promises 实现:读文件、写文件、创建目录、遍历目录、获取文件信息
  •  理解 Buffer 和字符串的区别,知道什么时候需要指定 'utf-8' 编码
  •  实现一个函数:递归遍历目录,输出所有文件的路径和大小
  •  能解释 __dirname 和 process.cwd() 在什么情况下值不同

Day 4(06/19)— async/await 与异常处理

  •  封装一个 async 文件读取函数,带完整的 try/catch 错误处理
  •  用 Promise.all 并行读取 5 个文件,输出总耗时
  •  用 Promise.allSettled 处理部分文件不存在的场景
  •  实现 safeAsync 工具函数:const [err, data] = await safeAsync(promise)
  •  完成阶段二练习任务(file-toolkit 项目)

Day 5(06/20)— HTTP 原生服务器基础

  •  用 http.createServer 创建服务器,浏览器访问 localhost:3000 返回 "Hello World"
  •  实现路由分发:GET /health、GET /api/time、POST /api/echo
  •  手动解析 POST 请求的 JSON body(监听 data + end 事件)
  •  设置正确的 Content-Type 和 CORS 响应头
  •  能解释 req.url 中路径和查询参数的分离方法

Day 6(06/21)— HTTP 实战与总结

  •  实现一个内存版 CRUD API(GET/POST/PUT/DELETE /api/items)
  •  处理 404 未知路由和 500 服务端错误的统一返回
  •  用 Postman 或 curl 测试所有接口,验证功能正确
  •  完成阶段三练习任务(mini-http-server 项目)
  •  回顾总结:手写 HTTP 服务器让你理解了框架的哪些能力

Day 7(06/22)— Nest 环境搭建

  •  安装 @nestjs/cli 并验证版本
  •  用 nest new 创建项目,选择 pnpm 作为包管理器
  •  启动 pnpm run start:dev,浏览器访问 localhost:3000 确认成功
  •  逐一阅读生成的文件,理解每个文件的职责(main.ts / app.module / controller / service)
  •  用 nest generate resource users 生成 CRUD 模块
  •  能解释 Module / Controller / Service 三层关系

Day 8(06/23)— Nest CRUD 实战

  •  实现 Users CRUD 的完整逻辑(先用内存数组存储)
  •  定义 CreateUserDto 和 UpdateUserDto,添加 class-validator 校验装饰器
  •  配置全局 ValidationPipe,测试参数校验是否生效
  •  配置 CORS 和环境变量
  •  用 Postman 测试全部 5 个 CRUD 接口
  •  完成阶段四练习任务(nest-demo 项目)
  •  全局回顾:从原生 http 到 Nest,框架解决了哪些痛点

七、学习资源推荐

资源 说明
Node.js 官方文档 fs、path、http 等内置模块的权威参考,重点看 fs/promises 和 http 章节
pnpm 官方文档 中文文档齐全,重点看"动机"和"使用"章节
Nest.js 官方文档 重点看 Introduction → Overview → Fundamentals 三章
JavaScript.info - async/await 异步编程的最佳入门讲解,配图和代码都很清晰
Node.js 错误处理指南 Joyent 出品的经典文章,理解可操作错误 vs 程序员错误

八、学习心态建议

不要贪多,每个知识点都动手写一遍,比看十遍教程有用。 Node 的核心基础其实不多,模块系统、异步 I/O、HTTP 模型这三块吃透了,后面学 Nest 或其他框架都会很快上手。

跳过 stream、cluster、worker_threads 这些冷门内容是正确的策略——它们在实际项目中用到时再查文档即可,现在学只会分散精力、打击信心。

重点把握一条主线:包管理 → 模块系统 → 文件操作 → 异步处理 → HTTP 服务 → Nest 框架。每一步都在为下一步铺垫,形成从底层原理到工程实践的完整认知链条。当你学完 Nest 回头再看,会发现框架帮你做的所有事情,本质上都是你在 HTTP 阶段手动做过的那些操作。


文档版本: v2.0
创建日期: 2026-06-15

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐