生成gRPC JS文件后运行报错:模块未提供指定导出
gRPC TypeScript项目运行时导出错误问题
生成proto JS/TS文件的命令
npx grpc_tools_node_protoc --js_out=import_style=commonjs,binary:./grpc/client --grpc_out=grpc_js:./grpc/client --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` -I ./grpc/proto ./grpc/proto/*.proto && npx protoc --plugin=protoc-gen-ts=`which protoc-gen-ts` --ts_out=grpc_js:./grpc/client -I ./grpc/proto ./grpc/proto/*.proto
运行时错误信息
$ export PORT=4433&&n run start > node.jsrestapi@1.0.0 start > export NODE_ENV=development&& node --experimental-specifier-resolution=node build/src/webapi/server.js file:///usr/src/Node.JSRestAPI/build/src/webapi/Services/SchoolService.js:5 import { CommonStudentsResponse as grpcCommonStudentsResponse, } from "../grpc/client/school_pb.js"; ^^^^^^^^^^^^^^^^^^^^^^ SyntaxError: The requested module '../grpc/client/school_pb.js' does not provide an export named 'CommonStudentsResponse' at ModuleJob._instantiate (node:internal/modules/esm/module_job:171:21) at async ModuleJob.run (node:internal/modules/esm/module_job:254:5) at async ModuleLoader.import (node:internal/modules/esm/loader:475:24) at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:109:5) Node.js v22.2.0
环境信息
- 操作系统:Ubuntu 24.04
- Node.js版本:22.2.0
- Node安装方式:apt
- 编译器:g++ 13.2.0
- 相关依赖版本:
"grpc_tools_node_protoc_ts": "^5.3.3", "@grpc/grpc-js": "^1.10.10", "@grpc/proto-loader": "^0.7.13",
问题描述
生成的产物文件中已定义CommonStudentsResponse符号,TypeScript项目构建时无报错,但运行时出现上述导出错误,请问遗漏了什么?
解决方法
1. 核心原因
你生成的JS文件是CommonJS格式(指定了import_style=commonjs),但项目运行时使用的是**ES模块(ESM)**加载方式。CommonJS用module.exports导出内容,ESM用export语法,直接用ESM的命名导入无法识别CommonJS的导出结构。
2. 优先解决方案:生成ESM格式的proto文件
修改生成命令中的--js_out参数,将导入风格改为module(ESM):
npx grpc_tools_node_protoc --js_out=import_style=module,binary:./grpc/client --grpc_out=grpc_js:./grpc/client --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` -I ./grpc/proto ./grpc/proto/*.proto && npx protoc --plugin=protoc-gen-ts=`which protoc-gen-ts` --ts_out=grpc_js:./grpc/client -I ./grpc/proto ./grpc/proto/*.proto
重新执行命令生成文件后,JS产物会使用ESM的export语法,此时ESM的命名导入就能正常识别。
同时确保tsconfig.json配置匹配ESM要求:
{ "compilerOptions": { "module": "ESNext", "moduleResolution": "NodeNext", "target": "ES2020", "outDir": "./build" } }
3. 临时替代方案:调整导入方式
如果暂时不想修改生成命令,可以将命名导入改为默认导入后解构:
import schoolPb from "../grpc/client/school_pb.js"; const { CommonStudentsResponse: grpcCommonStudentsResponse } = schoolPb;
这种方式能兼容CommonJS模块,但不推荐长期使用,建议优先切换到ESM格式的生成方式。
内容的提问来源于stack exchange,提问作者khteh
相关产品推荐
相关产品推荐

