Skip to content

序章

Node.js:从 JavaScript 到系统调用的全链路穿透

第一阶段:重新理解 Node.js 的本质

  • Node.js 不是语言,也不是框架,它是运行时(Runtime)
    基于 V8 的 JavaScript 执行环境 + libuv 的异步 I/O + C++ 绑定
  • CommonJS 模块系统:require() 的加载流程三步走
    路径分析 → 文件定位 → 编译执行(.js.json.node
  • 模块缓存:require 为什么是同步且高效的?
    Module._cache 如何避免重复加载?热更新的陷阱
  • __filename__dirname:它们从哪来?
    在编译阶段被注入的“魔法变量”
  • exports vs module.exports:导出机制的常见误解
    引用赋值 vs 对象属性修改

第二阶段:深入事件循环(Event Loop)

  • libuv 的事件循环架构:6 个阶段的精确顺序
    timers → I/O callbacks → idle/prepare → poll → check → close
  • setTimeout(fn, 0) 真的是立即执行吗?
    至少等待一个事件循环周期,可能更久
  • setImmediate() vs setTimeout(fn, 0):谁先执行?
    在 I/O 回调中注册时,setImmediate 优先;否则不确定
  • process.nextTick():不是事件循环的一部分,而是“微任务”
    它在每个阶段之间清空,优先级高于 Promise
  • 事件循环中的“饥饿”问题:CPU 密集任务如何阻塞 I/O?
    单线程模型的致命弱点,Worker Threads 的必要性

第三阶段:掌握核心模块与底层机制

  • Buffer:为什么需要它?JS 字符串无法处理二进制
    基于 C++ uint8_t[] 的内存分配,alloc vs allocUnsafe
  • Stream:背压(Backpressure)机制是如何工作的?
    highWaterMark_read()_write()、可读/可写流的内部队列
  • fs 模块:同步 vs 异步 vs 流式读取
    readFileSync 阻塞主线程,createReadStream 支持大文件
  • child_processspawnexecfork 的本质区别
    fork 创建 IPC 通道,用于主进程与子进程通信
  • cluster 模块:如何利用多核 CPU?
    主进程监听端口,子进程共享 socket(SO_REUSEADDR)

第四阶段:穿透 V8 与性能优化

  • V8 内存限制:为什么 Node.js 默认堆内存只有 ~1.4GB?
    32 位指针限制,可通过 --max-old-space-size 调整
  • 内存泄漏排查:heapdump + Chrome DevTools
    如何分析 retainers,找到未释放的闭包或缓存?
  • 性能分析:--prof + --prof-process 生成火焰图
    识别热点函数,优化关键路径
  • C++ 插件:N-API 为何能解决 ABI 兼容问题?
    抽象层隔离 V8 变更,实现跨版本兼容
  • AtomicsSharedArrayBuffer:多线程共享内存
    Worker Threads 中的原子操作与同步机制

第五阶段:理解模块加载与包管理

  • 模块解析算法:Node.js 如何查找 node_modules
    从当前目录向上递归,支持 package.jsonmain 字段
  • require.resolve():只解析路径,不执行模块
    用于静态分析、插件发现
  • ES Modules in Node.js:.mjstype: "module"
    静态分析、顶层 await、与 CommonJS 的互操作(createRequire
  • node_modules 扁平化:npm/yarn/pnpm 的不同策略
    pnpm 的硬链接 + 元数据文件如何节省磁盘空间?
  • NODE_PATH--preserve-symlinks:非标准路径加载
    微前端、monorepo 中的模块解析难题

第六阶段:生产环境高阶实践

  • 进程守护:systemdpm2forever 的对比
    pm2 的负载均衡、日志管理、热重载
  • 错误处理:未捕获异常与未处理 Promise 拒绝
    process.on('uncaughtException') 的风险与正确用法
  • 信号处理:SIGTERM vs SIGKILL,优雅关闭
    清理数据库连接、关闭服务器、退出进程
  • 安全加固:helmet、输入验证、防止 DoS
    HTTP 头部、速率限制、沙箱执行
  • 可观测性:日志、监控、追踪(OpenTelemetry)
    结构化日志、Prometheus 指标暴露

第七阶段:连接操作系统与网络底层

  • net 模块:TCP 服务器的 pause()resume()
    流量控制、背压传递
  • dgram 模块:UDP 的无连接通信
    DNS 查询、实时音视频传输
  • http 模块:Parser 如何处理请求头与 Body?
    基于 llparse 的状态机解析
  • HTTPS 与 TLS:crypto 模块的角色
    证书、密钥交换、加密套件
  • DNS 查询:dns.lookup() vs dns.resolve()
    前者走系统配置(/etc/nsswitch.conf),后者直接查 DNS 服务器