Node v22 中 JSON 导入报错 SyntaxError: Unexpected identifier 'assert' 的解决方法
问题描述
在升级到 Node.js v22 后,代码中导入 JSON 文件的语句:
javascript
import config from "./some-config-file.json" assert { type: "json" };
会引发以下错误:
SyntaxError: Unexpected identifier 'assert'
at compileSourceTextModule (node:internal/modules/esm/utils:337:16)
...其他堆栈跟踪
此问题仅出现在 Node v22 及以上版本,在 Node v21 及更早版本中相同代码可正常运行。
问题原因:Node v22 移除了对 import assert
语法的支持(原名为 "import assertions"),改用了新标准的 "import attributes" 语法。这是因为 ECMAScript 规范提案已将关键字从 assert
改为 with
。
解决方案
方法一:使用新语法 with
(推荐适用于 Node v18.20+)
最简单直接的解决方案是将 assert
替换为 with
:
javascript
import config from "./some-config-file.json" with { type: "json" };
注意事项:
- 此语法需要 Node v18.20 及以上版本
- 对于需要兼容 Node v16 和 v17 的项目:
- Node v16.14 和 v17.1 支持旧版
assert
语法 - 但 Node v16 和 v17 不支持新版
with
语法 - 如果项目需要多版本支持,请考虑其他替代方案
- Node v16.14 和 v17.1 支持旧版
方法二:使用 createRequire
加载 JSON(跨版本兼容方案)
如需保持旧版 Node 的兼容性(Node v12.2+),可使用 createRequire
方法加载 JSON:
javascript
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const config = require('./some-config-file.json');
优点:
- 支持从 Node v12.2.0 开始的所有版本
- 与原生
import
一样具备模块缓存机制 - 被广泛使用(如
import-from-esm
)
方法三:手动读取和解析 JSON(最低兼容方案)
使用原生 Node.js 模块手动读取和解析 JSON 文件:
javascript
import fs from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
// 获取当前模块路径
const currentDir = dirname(fileURLToPath(import.meta.url));
const configPath = join(currentDir, 'some-config-file.json');
// 异步读取并解析
const config = JSON.parse(await fs.readFile(configPath, 'utf-8'));
同步读取版:
javascript
import fs from 'node:fs';
// ...(同上路径获取)
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
注意事项
此方法相比原生import
:
- 每次调用都会重新读取文件(无模块缓存)
- 修改文件可能导致读取不一致
- 需要自行处理相对路径解析
优化建议:可封装为共享模块解决缓存问题:
javascript
// json-loader.js
import { createRequire } from 'node:module';
export const loadJSON = (path) => createRequire(import.meta.url)(path);
最佳实践选择指南
方案 | 优势 | 限制 | 推荐场景 |
---|---|---|---|
with 语法 | 最简洁,符合新标准 | 需 Node v18.20+ | 新项目/无需兼容旧版本 |
createRequire | 最佳兼容性(v12.2+),行为一致 | 比原生稍重 | 需兼容多个 Node 版本 |
手动解析 | 兼容所有 Node 版本 | 需手动处理路径和缓存 | 特殊环境或学习目的 |
升级建议
- 检查项目支持的 Node 版本范围(通过
.nvmrc
或package.json
的engines
字段) - 若能接受 Node v18.20 作为最低版本,优先选用
with
语法 - 对需要向后兼容的类库项目,建议使用
createRequire
方案
通过选择适合项目需求的解决方案,即可解决 Node v22 的 JSON 导入错误问题。