NodeJs各版本新特性(持续更新)
摘要:
Node.js最新版本分为Current系列和LTS系列,两者分别面向不同需求场景:前者提供最新功能,后者强调长期稳定性。本文主要以偶数版本介绍。
更新时间:2025-06-19
v22(使用 22.16.0 测试)
概览
实验性功能变为稳定的功能:
- 监视模式(--watch)稳定化
- 权限模型(v23.5.0、v22.13.0)
- WebSocket 客户端(v22.4.0)
- [import.meta][#import.meta]
- fetch:v21.0.0 不再是实验性的
新功能:
实验性功能:
开发者相对无感的底层更新:
监视模式(--watch)稳定化
新增于:(v18.11.0, v16.19.0),用于监视文件系统的变动,并自动重启。
v22.0.0 版本开始,这个指令成为稳定功能了。
要启用监视模式,只需要在启动 Node 应用时加上 --watch ****参数。例如:
bash
node --watch index.js
关于 watch mode 详情请查看:(v18.11.0, v16.19.0)测试监听模式、(v18.11.0, v16.19.0)#监听模式
权限模型
从v23.5.0、v22.13.0 开始, 此功能不再处于实验阶段。开启命令从--experimental-permission修改为--permission。
bash
node --permission --allow-fs-read=./ index.js
关于权限模型详情请看:(v20.0.0 介绍)新的权限模型
WebSocket 客户端
从 v22.4.0 开始WebSocket属于稳定功能,不再需要 --experimental-websocket 来启用了。
如果需要关闭使用--no-experimental-websocket来禁用。
关于WebSocket客户端请查看(v21.0.0, v20.10.0):内置 WebSocket 客户端
import.meta
新增于:v21.2.0, v20.11.0,在 v22.16.0 标记为稳定。
关于 import.meta 属性请查看(v21.2.0, v20.11.0):import.meta.resolve
支持通过 require() 引入 ESM
js
// CommonJS
// constant.mjs
export const str = 'hello world'
// test.mjs
import { str } from './constant.mjs'
export function output() {
console.log(str)
}
// index.js
const { output } = require('./test.mjs')
output() // hello world
注意项:
- 最新版本已默认开启,若未开启可使用
-experimental-require-module参数,如:node --experimental-require-module index.js- 模块标记:确保 ESM 模块通过
package.json中的"type": "module"或文件扩展名是.mjs。- 完全同步:只有完全同步的 ESM 才能被
require()导入,任何含有顶级await的 ESM 都不能使用这种方式加载。
运行 package.json 中的脚本
假设package.json有以下脚本:
json
{
"scripts": {
"dev": "node index.js"
}
}
以前我们都是通过 npm 来运行npm run dev,或者通过第三个包管理工具:pnpm dev、yarn dev等。
现在可以直接通过 node 运行,省略中间步骤,做到统一运行环境和提升性能。
bash
➜ npm run dev
> node@1.0.0 dev
> node index.js
hello world
➜ node --run dev
hello world
增加流的默认高水位线
虽然 highWaterMark 是可配置的,但通常情况下,我们是使用默认值。在以前的版本里,highWaterMark 的默认值是 16k,Node 22 版本开始,默认值被提升到 64k 了。
js
const fs = require('fs')
// 读取一个文件大小为:19433
const readStream = fs.createReadStream('test.md', {
highWaterMark: 64 * 1024
})
readStream.on('data', (chunk) => {
// 当highWaterMark:16 * 1024时,输出:Received chunk of size: 16384、Received chunk of size: 3049
// 当highWaterMark:16 * 1024时,输出:Received chunk of size: 19433
console.log(`Received chunk of size: ${chunk.length}`)
})
readStream.on('end', () => {
console.log('End of file has been reached.')
})
highWaterMark 越大,缓冲区越大,占用内存越多,I/O 操作就减少,highWaterMark 越小,其他信息也对应相反。
文件模式匹配功能
fs.glob和fs.globSync
js
const fs = require('fs')
fs.glob('./*.md', (err, files) => {
if (err) {
throw err
}
console.log(files) // ['./test.md']
})
const files = fs.globSync('./*.js')
console.log(files) // ['constant.js', 'index.js', 'test.js']
使用场景
- 自动化构建过程,如自动寻找和处理项目中的 JavaScript 文件。(比如 vue 路由放在指定目录,使用此方式自动导入。)
- 开发工具和脚本,需要对项目目录中的文件进行批量操作。
- 任何需要从大量文件中快速筛选出符合特定模式的文件集的应用。
ts 运行支持
Node.js v22.6.0 版本通过 --experimental-strip-types 标志,实现了对 TypeScript 的实验性支持。
这意味着开发者们现在可以在 Node.js 环境中直接执行 .ts 文件,而无需进行额外的编译步骤。
ts
// index.ts
console.log('hello world')
bash
node --experimental-strip-types index.ts // hello world!
V8 引擎升级至 12.4 版本
- WebAssembly 垃圾回收:这一特性将改善 WebAssembly 在内存管理方面的能力。
- Array.fromAsync:这个新方法允许从异步迭代器创建数组。
- Set 方法和迭代器帮助程序:提供了更多内建的 Set 操作和迭代器操作的方法,增强了数据结构的操作性和灵活性。
Maglev 编译器默认启用
Maglev 是 V8 的新编译器,现在在支持的架构上默认启用。它主要针对短生命周期的命令行程序(CLI 程序)性能进行优化,通过改进 JIT(即时编译)的效率来提升性能。这对开发者编写的工具和脚本将带来明显的速度提升。
改进 AbortSignal 的创建性能
在这次更新中,Node 提高了 AbortSignal 实例的创建效率。AbortSignal 是用于中断正在进行的操作(如网络请求或任何长时间运行的异步任务)的一种机制。通过提升这一过程的效率,可以加快任何依赖这一功能的应用,如使用 fetch 进行 HTTP 请求或在测试运行器中处理中断的场景。
AbortSignal 的工作方式是通过 AbortController 实例来管理。AbortController 提供一个 signal 属性和一个 abort() 方法。signal 属性返回一个 AbortSignal 对象,可以传递给任何接受 AbortSignal 的 API(如 fetch)来监听取消事件。当调用 abort()方法时,与该控制器关联的所有操作将被取消。
js
const controller = new AbortController()
const signal = controller.signal
fetch(url, { signal })
.then((response) => response.json())
.catch((err) => {
if (err.name === 'AbortError') {
console.log('请求取消')
} else {
console.error('请求错误:', err)
}
})
// 取消请求
controller.abort()
参考:
https://blog.csdn.net/jjc4261/article/details/139440329
https://nodejs.org/zh-cn/blog/release/v22.0.0
v20
概览
稳定的实验性功能:
实验性功能变动
新增的实验性功能:
其他变动及改进:
- Web Crypto API 改进
- ARM64 Windows 支持
- HTTP/1.1 默认 Keep-Alive: 提高连接复用效率。
- V8 引擎升级到 11.3
- Web Assembly 系统接口(WASI)进展。
- 性能优化
- EventTarget: 初始化成本减少 50%,加速相关子系统(如 fetch)。
- V8 Fast API: 用于优化 URL.canParse() 和定时器等 API 的性能。
新的权限模型
权限模型是一种在执行期间对特定资源限制访问的机制。要启用改机制,需要在 node 运行脚本时,添加--experimental-permission参数,启用该机制后,将限制对所有可用权限的访问。
bash
node --permission index.js
此时执行脚本将会报以下错误:Error: Access to this API has been restricted
可以通过以下参数给指定文件或文件间授权:
bash
--allow-fs-read=* # 允许读取的文件
--allow-fs-write=* # 允许写入的文件
其中*可以是文件目录,文件路径或者是路径通配符,如以下:
bash
# 仅允许入口脚本文件可读
node --experimental-permission --allow-fs-read=index.js index.js
# 当前目录下所有文件可读
node --experimental-permission --allow-fs-read=./ index.js
# 当前目录下,所有js文件可读
node --experimental-permission --allow-fs-read="./*.js" index.js
# 当前目录及同级test目录可读,多次使用--allow-fs-read参数
node --experimental-permission --allow-fs-read=./ --allow-fs-read=../test index.js
应用内检查是否有权限:permission.has(scope[, reference])
其中:scope可选值有:fs.write、fs.read,reference参数可选,不传则为当前目录,可以传递目录、文件地址、路径通配符。
js
process.permission.has('fs.write') // 获取当前目录是否有写的权限
process.permission.has('fs.write', '../test') // 获取指定目录是否有写的权限
process.permission.has('fs.write', './*.js') // 获取指定路径通配符是否有写的权限
process.permission.has('fs.read') // 获取当前目录是否有读的权限
process.permission.has('fs.read', '/home/rafaelgss/protected-folder') // 获取指定目录是否有读的权限
其他权限扩展
- 子进程权限:--allow-child-process
- 多线程权限:--allow-worker
- 原生插件权限:--allow-addons
- WASI 权限:--allow-wasi
当使用权限控制的同时,也是有了上方的功能,就需要添加上方的参数以授权,若上方的功能内使用到了文件的读取或写入操作,也需要使用--allow-fs-read或--allow-fs-write配置文件授权。
bash
# 允许子进程权限
node --experimental-permission --allow-child-process --allow-fs-read=* process.js
# 其他相同
# ...
内置 WebSocket 客户端
在(v21.0.0, v20.10.0)版本添加,需要 --experimental-websocket 来启用。
除此之外,WebScoket 的实现还遵循了浏览器中 WebSocket API 的标准,这意味着在 Node 中使用 WebSocket 的方式将与在 JavaScript 中使用 WebSocket 的方式非常相似,有助于减少学习成本并提高代码的一致性。
注意:
这个是用于客户端的,如果创建服务端,还是推荐使用上面的三方库:ws、socket.io
js
// 无需导入,直接使用
const socket = new WebSocket('ws://localhost:8800')
socket.addEventListener('open', (event) => {
socket.send('Hello Server!')
})
socket.addEventListener('error', (event) => {
console.log('WebSocket error:', event)
})
测试模式稳定
从 v20.0.0 开始,Test Running标记为稳定。可以通过--test **启动。
bash
node --test index.js
使用内置的 node:test 和 node:assert 模块,支持基本的测试用例编写、断言和报告生成。
js
const { test } = require('node:test')
const assert = require('node:assert')
test('加法测试', () => {
assert.strictEqual(1 + 1, 2)
})
关于Test Running详情请查看:(v18.11.0, v16.19.0)测试监听模式、(v18.1.0, v16.17.0)#测试模式
注意:不能和
--watch-path,--check,--eval,--interactive同时使用
ESM Loader
自定义 ESM 加载器钩子在专用线程上运行,与主线程隔离。这为加载器提供了单独的作用域,并确保加载器和应用程序代码之间不会发生交叉污染。(官方建议使用--import来自定义钩子)
bash
node --experimental-loader=./register-hooks.mjs ./index.js
node --import ./register-hooks.mjs ./index.js
示例:从 HTTPS 导入(注意:package.json里配置type: "module",或者文件后缀使用.mjs),这是 ESM 的加载器钩子。
js
// index.js
import { VERSION } from 'https://coffeescript.org/browser-compiler-modern/coffeescript.js'
console.log(VERSION)
// https-hooks.mjs
import { get } from 'node:https'
export function load(url, context, nextLoad) {
if (url.startsWith('https://')) {
return new Promise((resolve, reject) => {
get(url, (res) => {
let data = ''
res.setEncoding('utf8')
res.on('data', (chunk) => (data += chunk))
res.on('end', () =>
resolve({
format: 'module',
shortCircuit: true,
source: data
})
)
}).on('error', (err) => reject(err))
})
}
return nextLoad(url)
}
// 运行
node --import 'data:text/javascript,import { register } from "node:module"; import { pathToFileURL } from "node:url"; register(pathToFileURL("./https-hooks.mjs"));' ./main.mjs
import.meta.resolve
在 ESM 中,import.meta.resolve() 现在同步返回模块路径,与浏览器行为一致。
其他 import.meta 属性:添加于:v21.2.0, v20.11.0
如果您习惯于 Node.js 的 CommonJS 模块,使用 **filename 和 **dirname 获取文件目录名和路径。那么在 ESM 中可以使用以下代码来替代。
js
import.meta.dirname // 当前模块的绝对完整目录
import.meta.filename // 模块的完整绝对路径和文件名
import.meta.url // 模块的绝对url
url.parse()
替换了旧版 Ada 1.0.4,全面集成到 Node.js 中,用于解析 URL。优化了 url.parse() 和 url.domainToUnicode 等功能。性能显著提升,且不再依赖 ICU(国际化组件)进行主机名解析。
单执行应用程序
允许将 Node.js 应用打包为单个可执行文件,无需单独安装 Node.js 运行时。
bash
# 创建应用配置文件,入口及出口
echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json
# 生成blob文件
node --experimental-sea-config sea-config.json
# 创建副本,并根据需要改名
cp $(command -v node) hello # 非win
node -e "require('fs').copyFileSync(process.execPath, 'hello.exe')" # win改名为后缀.exe
# 删除二进制文件的签名(仅mac和win)
codesign --remove-signature hello # mac
signtool remove /s hello.exe # win
# 通过postject,将blob注入到复制的二进制文件中
npx postject hello NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 # linux
npx postject hello.exe NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 # win
npx postject hello NODE_SEA_BLOB sea-prep.blob --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 --macho-segment-name NODE_SEA # mac
# 签名二进制文件(仅mac和win)
codesign --sign - hello # mac
signtool sign /fd SHA256 hello.exe # win
# 运行二进制文件
./hello world # 非win
./hello.exe world # win
缺点:配置麻烦,使用到的静态资源需要在配置文件配置,并且对于比较大的项目使用会有各种问题,大项目还是建议使用别的工具,比较 ncc
环境变量文件配置
要加载 .env 文件,可以在启动 Node.js 应用时使用 --env-file CLI 标志。该标志指定要加载的 .env 文件路径。
bash
# 单个文件
node --env-file=./.env ./index.js
# 多个文件,依次加载,后面的覆盖前面的
node --env-file=./.env --env-file=./.env.development ./index.js
js
// 使用环境变量
console.log(process.env.PORT)
v18
实验性功能:
实验性功能稳定:
其他变动及改进:
- Blob API:新增了 Blob API,封装了不可变的原始数据,可以在多个工作线程之间安全地共享这些数据。此外,新增的 BroadcastChannel 实例允许与绑定到同一 channel name 的所有其他 BroadcastChannel 实例进行异步一对多通信。
- Web Streams API:Node.js 18 支持 Web Streams API,允许 JavaScript 以编程方式访问通过网络接收的数据流,提高了处理大数据的能力。
- V8 引擎升级:V8 引擎升级到 10.1 版本,带来了新的数组方法如 findLast()和 findLastIndex(),提升了处理大量数据的能力
- 性能优化:Node.js 18 在性能方面进行了优化,提升了代码执行速度和内存利用率,特别是在处理大量并发请求时表现更出色
- 构建工具集成:与 Webpack 的集成更加紧密,实现了代码的压缩、合并、拆分等功能,提高了项目的构建效率和性能
测试监听模式
新增于:(v19.2.0, v18.13.0),在测试模式下,也可以使用监听模式了。
之前版本同时使用是会报错:
bash
# node: either --test or --watch can be used, not both
node --test --watch index.js
之后版本就可以同时使用了。
关于 watch mode 详情请查看:(v18.11.0, v16.19.0)#监听模式
关于 test running 详情请查看:(v18.1.0, v16.17.0)#测试模式
fetch 不再需要--experimental-fetch
新增于:(v17.5.0, v16.15.0),用于在 node 中发起 HTTP 请求。
从 v18.0.0 不再需要使用--experimental-fetch,在 v21.0.0 标记为稳定
js
const res = await fetch('https://nodejs.org/api/documentation.json')
if (res.ok) {
const data = await res.json()
console.log(data)
}
v16
实验性功能:
其他变动及改进:
- V8 引擎升级 :将 V8 升级至 9.0 版本,带来性能提升(如 Promise 和 Async/Await 的性能优化约 20%)。
- 底层依赖升级 :
- llhttp 升级至 6.0.0,优化 HTTP 报文解析性能。
- ICU(国际化组件)升级至 69.1 版本,增强国际化支持。
- Web Crypto API 的试验性支持 :提供加密功能接口(如签名、加密等),增强安全性。
- AbortController 的稳定实现 :允许开发者中断长时间运行的异步任务(如网络请求),提升资源利用率。
监听模式
新增于:(v18.11.0, v16.19.0),用于监视文件系统的变动,并自动重启。
要启用监视模式,只需要在启动 Node 应用时加上 --watch ****参数。例如:
bash
node --watch index.js
这样不管是index.js发生改变,还是index.js依赖的文件发生改变,都会重新运行了。如果只需要监听文件改变重新运行,可以替代了nodemon包了。
注意:不能和
--test同时使用
测试模式
新增于:(v18.1.0, v16.17.0),用于监视文件系统的变动,并自动重启。
要启用测试模式,只需要在启动 Node 应用时加上 --test ****参数。例如:
使用内置的 node:test 和 node:assert 模块,支持基本的测试用例编写、断言和报告生成。
js
const { test } = require('node:test')
const assert = require('node:assert')
test('加法测试', () => {
assert.strictEqual(1 + 1, 2)
})
bash
node --test index.js
fetch
现代化的网络请求,替代 http 模块中的一些功能。
bash
node --experimental-fetch index.js
js
const res = await fetch('https://nodejs.org/api/documentation.json')
if (res.ok) {
const data = await res.json()
console.log(data)
}
promise 支持
- setTimeout 和 setInterval 被改造为返回 Promise 的形式,支持异步迭代器(如 for await),简化异步代码编写。
- AbortController API 的实现,用于中断异步操作(例如网络请求或文件读写)
js
const { setTimeout, setInterval } = require('node:timers/promises')
setTimeout(2000).then(() => {
console.log('123') // 123
})
setTimeout(2000, '345').then((res) => {
console.log(res, '123') // 345, 123
})
评论
0条评论
暂无内容,去看看其他的吧~



