和Node.js的Buffer说拜拜

声明:(1)此文为译文,原文见 Goodbye, Node.js Buffer (2)翻译不准处的后面加上了英文原文词汇或进行了不影响理解的删减(3)翻译不对的地方请不吝赐教,留言更正(4)为了使文章更具有可读性,译者适当地增加了标题和划分了段落。

Buffer存在的缺欠

Buffer类型从一开始就是Node.js中处理二进制数据的基石。然而,现在我们有了 Uint8Array,这是一个原生的 JavaScript 类型并且可以跨平台工作。而 Buffer 是 Uint8Array 的一个实例,它引入了许多在其他 JavaScript 环境中不可用的方法。因此,那些使用了特定于Buffer的方法(Buffer-specific methods)的相关代码需要进行填充(polyfilling),这阻碍了许多有价值的包和浏览器兼容。

Buffer 还带了一些额外的问题。例如:

第一,Buffer的slice()方法,创建了一个链接到原始缓冲区的可变片段(segment ),会导致一些不可预测的行为,然而 Uint8Array的slice()方法则创建了一个不可变的副本。问题不在于Buffer的slice()方法的行为,而在于Buffer是Uint8Array的子类,它完全改变了继承自Uint8Array的方法的行为。可以使用Unit8Array的subarray()方法或者Buffer的subarray()方法代替Buffer的slice()方法。

第二,Buffer通过全局变量暴露隐私信息,这是一个潜在的安全风险。

我们是时候和Buffer说拜拜了!

我的升级计划

我打算将我所有的包从使用 Buffer 改为Uint8Array。如果您是 JavaScript 包的维护者,我鼓励您也这样做。Buffer可能永远不会被删除,甚至可能永远不会被弃用,但至少社区可以慢慢远离它,我希望 Node.js 团队至少开始不鼓励使用 Buffer。

如何进行升级

首先,熟悉 Uint8Array 和 Buffer 之间微妙的不兼容性。我已经开发了uint8array-extras包来使转换更加容易。

如果你的代码使用了 Buffer 并且没有使用任何特定于 Buffer 的方法( Buffer-specific methods),那么只需将文档和数据类型更新为 Uint8Array 即可。

将输入类型从 Buffer 更改为 Uint8Array 是非破坏性更改,因为 Buffer 是 Uint8Array 的实例。

将返回类型从 Buffer 更改为 Uint8Array 是一个重大更改,因为返回值的消费者可能使用特定于Buffer的方法(Buffer-specific methods)。

如果你确实需要将 Uint8Array 转换为 Buffer,可以使用 Buffer.from (uint8Array)(拷贝数据)或者 Buffer.from(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength)(不拷贝数据)。然而还有更好的方法吗?

一些主要的修改步骤是:

  • 删除所有的import {Buffer} from 'node:buffer' 导入语句
  • 删除所有的Buffer全局变量
  • 停止使用特定于Buffer的方法
  • 替换 Buffer的读/写方法,例如用DataView替换Buffer的readInt32BE()方法

解答一些问题

1.Buffer 为什么一开始会存在?

在 Uint8Array 存在之前很久就已经创建了 Buffer。

2.如何使用 Uint8Array 进行与 Base64之间的转换?

你现在可以使用我的 uint8array-extras 包,它很可能最终会在 原生JavaScript 中得到支持。

3.如何处理返回Buffer的 Node.js API,比如 fs 的方法?

因为 Buffer 是 Uint8Array 的一个子类,所以您可以将它看作 Uint8Array。只要确保不使用. slice ()(它在行为上有所不同)或任何特定于 Buffer 的方法( Buffer-specific methods)。

例子

Javascript代码

JavaScript 复制代码
+ import {stringToBase64} from 'uint8array-extras';

- Buffer.from(string).toString('base64');
+ stringToBase64(string);
JavaScript 复制代码
+ import {uint8ArrayToHex} from 'uint8array-extras';

- buffer.toString('hex');
+ uint8ArrayToHex(uint8Array);
JavaScript 复制代码
const bytes = getBytes();

+ const view = new DataView(bytes.buffer);

- const value = bytes.readInt32BE(1);
+ const value = view.getInt32(1);
JavaScript 复制代码
import crypto from 'node:crypto';
- import {Buffer} from 'node:buffer';
+ import {isUint8Array} from 'uint8array-extras';

 export default function hash(data) {
	- if (!(typeof data === 'string' || Buffer.isBuffer(data))) {
	+ if (!(typeof data === 'string' || isUint8Array(data))) {
 		throw new TypeError('Incorrect type.');
 	}

 	return crypto.createHash('md5').update(data).digest('hex');
 }

大多数 Node.js API 也接受 Uint8Array,因此不需要额外的工作。

TypeScript代码

TypeScript 复制代码
- import {Buffer} from 'node:buffer';

- export function getSize(input: string | Buffer): number { ... }
+ export function getSize(input: string | Uint8Array): number { ... }

强制使用Unit8Array

我建议使用 lint工具(linting)强制使用 Uint8Array 而不是 Buffer,将如下内容增加到你的ESLint配置当中:

JavaScript 复制代码
{
	'no-restricted-globals': [
		'error',
		{
			name: 'Buffer',
			message: 'Use Uint8Array instead.'
		}
	],
	'no-restricted-imports': [
		'error',
		{
			name: 'buffer',
			message: 'Use Uint8Array instead.'
		},
		{
			name: 'node:buffer',
			message: 'Use Uint8Array instead.'
		}
	]
}

如果你使用的是TypeScript则使用如下内容:

TypeScript 复制代码
{
	'@typescript-eslint/ban-types': [
		'error',
		{
			types: {
				Buffer: {
					message: 'Use Uint8Array instead.',
					suggest: [
						'Uint8Array'
					]
				}
			}
		}
	]
}
相关推荐
雪碧聊技术7 分钟前
前端VUE3项目部署到linux服务器(CentOS 7)
前端·linux部署vue3项目
酒尘&6 小时前
JS数组不止Array!索引集合类全面解析
开发语言·前端·javascript·学习·js
学历真的很重要6 小时前
VsCode+Roo Code+Gemini 2.5 Pro+Gemini Balance AI辅助编程环境搭建(理论上通过多个Api Key负载均衡达到无限免费Gemini 2.5 Pro)
前端·人工智能·vscode·后端·语言模型·负载均衡·ai编程
用户47949283569158 小时前
"讲讲原型链" —— 面试官最爱问的 JavaScript 基础
前端·javascript·面试
用户47949283569158 小时前
2025 年 TC39 都在忙什么?Import Bytes、Iterator Chunking 来了
前端·javascript·面试
大怪v9 小时前
【Virtual World 04】我们的目标,无限宇宙!!
前端·javascript·代码规范
狂炫冰美式9 小时前
不谈技术,搞点文化 🧀 —— 从复活一句明代残诗破局产品迭代
前端·人工智能·后端
xw510 小时前
npm几个实用命令
前端·npm
!win !10 小时前
npm几个实用命令
前端·npm
代码狂想家10 小时前
使用openEuler从零构建用户管理系统Web应用平台
前端