NestJS导入protoc生成的protobuf文件提示Cannot find module报错
NestJS 导入protoc生成的PB文件报模块找不到的排查方案
问题背景
- 执行的PB生成命令如下:
protoc --plugin="protoc-gen-ts=.\\node_modules\\.bin\\protoc-gen-ts.cmd" --plugin="protoc-gen-grpc=.\\node_modules\\.bin\\grpc_tools_node_protoc_plugin.cmd" --js_out="import_style=commonjs,binary:./src/protos/interfaces" --ts_out="service=grpc-node,mode=grpc-js:./src/protos/interfaces" --grpc_out="./src/protos/interfaces" ./src/protos/*.proto
- 命令执行完成后,已成功生成
login_pb.js、login_pb.d.ts两个文件 - 确认导入路径书写逻辑无误,使用的导入语句为:
import * as LoginPB from '../protos/interfaces/src/protos/login_pb';
- 运行时抛出错误:
Error: Cannot find module '../protos/interfaces/src/protos/login_pb'
排查解决步骤
按顺序核对以下配置,绝大多数同类问题都能定位解决:
- 第一步:核对文件实际存放路径
你当前执行protoc命令时没有加-I(即--proto_path)参数指定proto文件根目录,protoc默认会将传入的proto文件的相对路径完整拼接在输出目录后,非常容易出现路径多嵌套层级的问题。不要凭记忆判断路径,直接打开文件管理器逐层进入目录,确认login_pb.js的真实存放位置,将导入路径修改为和真实路径完全一致即可。 - 第二步:补全导入语句的
.js后缀
Node.js运行时加载CommonJS模块时,部分版本不会自动补全本地文件的.js后缀,TS类型检查阶段识别.d.ts文件不需要写后缀,但运行时加载的是实际的JS文件,把导入语句修改为如下写法:import * as LoginPB from '../protos/interfaces/src/protos/login_pb.js'; - 第三步:检查NestJS构建配置
NestJS默认构建时只会编译.ts文件,不会主动拷贝目录下的.js、.proto文件到输出的dist目录,如果没有做静态资源配置,构建后产物里根本不存在生成的PB文件,运行时必然报模块不存在。打开项目根目录的nest-cli.json,添加如下静态资源配置:
同时打开{ "compilerOptions": { "assets": ["**/*.proto", "protos/**/*.js"], "watchAssets": true } }tsconfig.json,确认compilerOptions.moduleResolution配置为node或者NodeNext,避免模块解析逻辑异常。 - 第四步:排查模块规范兼容问题
你生成PB文件时指定了import_style=commonjs,输出的JS文件为CommonJS格式。检查项目根目录package.json中是否配置了"type": "module",如果存在该配置,Node.js会将所有.js文件按ES模块规范解析,和CommonJS格式的PB文件不兼容,移除该配置或者重新生成ES模块格式的PB文件即可。
内容的提问来源于stack exchange,提问作者AMit SiNgh
相关产品推荐
相关产品推荐

