memfs vs memory-fs
内存文件系统在 Node.js 工具链中的实现对比
memfsmemory-fs类似的npm包:
内存文件系统在 Node.js 工具链中的实现对比

memfsmemory-fs 都是用于在内存中模拟 Node.js 文件系统的工具库,常用于测试、构建工具(如 Webpack)或需要隔离文件操作的场景。它们提供与原生 fs 模块兼容的 API,允许开发者在不实际读写磁盘的情况下进行文件操作。memfs 是一个活跃维护的现代替代方案,而 memory-fs 已被官方标记为废弃,不再推荐用于新项目。

npm下载趋势
3 年
GitHub Stars 排名
统计详情
npm包名称
下载量
Stars
大小
Issues
发布时间
License
memfs27,156,6192,02828.3 kB4811 天前Apache-2.0
memory-fs10,327,489879-306 年前MIT

memfs vs memory-fs:内存文件系统的现代替代方案

在开发构建工具、测试环境或需要隔离文件 I/O 的 Node.js 应用时,我们常常需要一个不依赖真实磁盘的文件系统实现。memfsmemory-fs 都试图解决这个问题,但它们的现状、能力与维护状态截然不同。本文将从技术细节出发,帮助你做出正确选择。

🚫 重要前提:memory-fs 已被废弃

首先必须明确:memory-fs 已在 npm 上被官方标记为 deprecated(废弃)。其 GitHub 仓库的 README 明确写道:“This package is deprecated. Use memfs instead.”

这意味着:

  • 不再有功能更新或安全修复
  • 不兼容较新的 Node.js 特性(如 Promise 化的 fs API)
  • 社区和工具链(如 Webpack 5+)已全面转向 memfs

因此,除非你在维护一个尚未升级的旧项目,否则不应在新代码中引入 memory-fs

🔧 API 兼容性:谁更接近原生 fs

memfs:几乎完整的 fs 替代

memfs 的目标是提供一个与 Node.js 原生 fs 模块行为一致的内存实现。它不仅支持回调风格,还完整支持 fs.promisesfs.Stats 对象。

// 使用 memfs
import { fs } from 'memfs';

// 回调风格
fs.writeFile('/test.txt', 'hello', (err) => {
  if (err) throw err;
  fs.readFile('/test.txt', 'utf8', (err, data) => {
    console.log(data); // 'hello'
  });
});

// Promise 风格(现代推荐)
await fs.promises.writeFile('/test.txt', 'world');
const content = await fs.promises.readFile('/test.txt', 'utf8');
console.log(content); // 'world'

它还支持 fs.createReadStream / fs.createWriteStream,这对构建工具处理大文件至关重要。

memory-fs:仅基础回调 API

memory-fs 仅实现了部分回调风格的 fs 方法,不支持 Promise API,也不完全兼容 fs.Stats 或流操作。

// 使用 memory-fs(已废弃)
const MemoryFileSystem = require('memory-fs');
const fs = new MemoryFileSystem();

fs.writeFileSync('/test.txt', 'hello');
const content = fs.readFileSync('/test.txt', 'utf8');
console.log(content); // 'hello'

// ❌ 以下代码会失败或行为异常:
// fs.promises 不存在
// fs.createReadStream 可能不完整或缺失

如果你尝试在需要流式处理的场景(如 Webpack 的 asset emit)中使用 memory-fs,很可能会遇到兼容性问题。

🧪 功能完整性:符号链接、权限、时间戳

memfs 支持高级文件系统特性

  • 符号链接(symlink, readlink
  • 文件权限(chmod, stat.mode
  • 访问/修改时间戳(atime, mtime
  • 目录遍历(readdir with options)
// memfs 支持符号链接
await fs.promises.symlink('/target.txt', '/link.txt');
const target = await fs.promises.readlink('/link.txt');
console.log(target); // '/target.txt'

这些特性对于模拟真实文件系统行为(如测试 CLI 工具)至关重要。

memory-fs 功能有限

memory-fs 缺少对符号链接、精确时间戳和权限位的支持。它的 stat 对象是简化版,很多字段为固定值或 null

// memory-fs 的 stat 对象可能缺少关键字段
const stats = fs.statSync('/test.txt');
console.log(stats.mtime); // 可能是 Date 对象,但不随写入更新
console.log(stats.mode);  // 可能不反映真实权限

🛠️ 与构建工具的集成

Webpack 4 曾使用 memory-fs 作为默认输出文件系统,但从 Webpack 5 开始,已切换到 memfs。如果你在编写自定义 Webpack 插件或 loader 并需要操作内存文件系统,必须使用 memfs 才能与现代 Webpack 兼容。

// Webpack 5+ 中获取内存文件系统
compiler.outputFileSystem = require('memfs').fs;

尝试在 Webpack 5+ 中注入 memory-fs 实例会导致类型错误或运行时异常。

📦 初始化与挂载

两者都允许预填充初始文件结构,但 memfs 的方式更灵活。

// memfs:通过 vol.fromJSON 初始化
import { Volume } from 'memfs';
const vol = Volume.fromJSON({
  '/src/index.js': 'console.log("hello");',
  '/package.json': '{"name":"test"}'
});
const fs = vol.fs;
// memory-fs:需手动写入
const fs = new MemoryFileSystem();
fs.mkdirpSync('/src');
fs.writeFileSync('/src/index.js', '...');

memfsfromJSON 方法让测试 setup 更简洁、可读。

✅ 总结:为什么 memfs 是唯一合理选择

特性memfsmemory-fs
维护状态✅ 活跃维护❌ 已废弃
Promise API✅ 完整支持❌ 不支持
流式操作✅ 完整支持⚠️ 部分或缺失
符号链接✅ 支持❌ 不支持
Webpack 5+ 兼容✅ 官方使用❌ 不兼容
初始化便捷性fromJSON 快速填充⚠️ 需手动创建

💡 最终建议

  • 新项目:直接使用 memfs,它是当前事实标准。
  • 旧项目仍在用 memory-fs:制定迁移计划,替换为 memfs。通常只需更改 import/require 语句并调整少量 API 调用(如使用 fs.promises)。
  • 编写测试或工具:利用 memfsVolume.fromJSON 和完整 API,让你的代码更健壮、更贴近真实环境。

记住:在工程实践中,选择一个仍在维护、功能完整、社区支持良好的依赖,远比节省几行配置更重要。memfs 正是这样的选择。

如何选择: memfs vs memory-fs
  • memfs:

    选择 memfs 如果你需要一个功能完整、与 Node.js fs 模块高度兼容且仍在积极维护的内存文件系统实现。它支持 Promise API、流式操作和符号链接等高级特性,适合集成到现代构建工具、测试框架或任何需要可靠虚拟文件系统的场景。

  • memory-fs:

    不要在新项目中使用 memory-fs。该包已在 npm 上被标记为废弃(deprecated),官方推荐迁移到 memfs。仅在维护遗留代码且暂时无法升级时才考虑保留它,但应尽快规划替换方案。

memfs的README

memfs

In-memory file system with Node.js fs API and browser File System (Access) API.

npm

Overview

memfs is a JavaScript library that implements an in-memory file system compatible with Node.js fs module and the browser File System (Access) API. Use it for testing, mocking file systems, or creating virtual file systems in both Node.js and browser environments.

Installation

npm install memfs

Quick Start

Node.js fs API

import { fs } from 'memfs';

// Write a file
fs.writeFileSync('/hello.txt', 'Hello, World!');

// Read a file
const content = fs.readFileSync('/hello.txt', 'utf-8');
console.log(content); // "Hello, World!"

// Create a directory
fs.mkdirSync('/mydir');

// List directory contents
console.log(fs.readdirSync('/')); // ['hello.txt', 'mydir']

Browser File System API

import { fsa } from 'memfs';

// Get root directory handle
const root = await fsa.getRoot();

// Create a file
const file = await root.getFileHandle('hello.txt', { create: true });
const writable = await file.createWritable();
await writable.write('Hello, World!');
await writable.close();

// Read the file
const readable = await file.getFile();
const text = await readable.text();
console.log(text); // "Hello, World!"

Features

  • Node.js fs module API compatibility
  • Browser File System (Access) API implementation
  • Adapters between fs and File System API
  • Directory snapshots and tree printing utilities
  • Works in Node.js and modern browsers
  • TypeScript support

Documentation

For detailed documentation and more examples, visit the main project page.

License

Apache 2.0