Node.js 文件系统与 path:fs API 与路径心智

Stream 那篇已经说过:大文件别一次性读进内存。落到日常工程里,更多时候是 「这个路径怎么拼、该用哪个 fs API、异步和同步怎么选」
这一篇围绕 文件与路径 展开,想讲清楚几件事:path 在解决什么问题、fs.promises 与回调版怎么对应、以及 watch、权限这类边缘能力在系统里处于什么位置

path 模块处理的是 跨平台差异

  • Windows 用 \,POSIX 用 /
  • path.join 按当前平台规则拼接,path.resolve 从右往左「吃掉」相对段,得到绝对路径;
  • path.normalize 去掉冗余的 . / ..

常见坑:

  • 手写字符串拼接路径 → 换系统就裂;
  • URL 路径文件系统路径 混用(file://、编码问题)。

习惯:凡是进磁盘的路径,先过 path 工具函数,而不是模板字符串硬凑。

Node 里 fs 同时存在多套风格:

  • 回调fs.readFile(path, cb),老代码多;
  • Promisefs.promises.readFileimport { readFile } from 'fs/promises'
  • 同步*Sync,阻塞事件循环。

选型可以记一条底线:

  • 服务端请求路径里默认不要 Sync
  • CLI 启动阶段、单次脚本Sync 有时更简单。

和 Stream 的配合:

  • 大文件用 createReadStream / createWriteStream
  • 小文件、配置用 readFile / writeFile 往往够用。

fs.readdir 列出目录;要递归往往自己写或使用 fs.readdir + 队列,或交给 专门的库

注意:

  • 符号链接权限错误极深目录树 都会让「递归读一遍」变成炸弹;
  • node_modules 这种目录要特别谨慎。

工程上经常是:

  • 按 glob 规则(构建工具)或 按已知子目录 读,而不是全盘扫。

文件变更监听常用于 开发时热重载轻量配置刷新

现实:

  • 各 OS 行为不一致,高频变更时可能 抖动
  • 网络文件系统上可靠性更差。

含义:

  • 生产环境依赖「watch 配置文件」要慎重,更常见是 外部信号(SIGHUP)、配置中心推送、或 定期拉取

创建文件、目录时会碰到 mode(如 0o644),以及 fs.open 的 flagaw+ 等)。

要点:

  • 默认 umask 会影响最终权限;
  • 并发写同一文件 要用 独占打开上层锁,不能指望「碰巧不冲突」。

这类细节通常在 第一次部署到 Linux 时集中爆发,本地 Windows 开发未必能提前暴露。

  • path 解决跨平台拼接与规范化;
  • fs 在回调 / Promise / Stream / Sync 之间选对层级;
  • 监听与递归 有平台和性能边界,生产上要收敛策略。

把文件层理顺,后面接日志落盘、静态资源、上传临时目录、Docker 卷挂载,都会少踩一层坑。