Skip to Content
🎉 gRPCity 3.0 is released. Read more →

Loader

ProtoLoadergRPCity 其他所有能力的入口。先用 proto 文件位置的描述构造它,然后调用一次 init();同一个实例可以同时驱动 client 和 server。

import { ProtoLoader } from 'grpcity' const loader = new ProtoLoader({ location, files })

两个参数分工不同:

  • location:loader 搜索的根目录,包含被引用的 model.protoempty.proto 等独立引用文件。
  • files:要加载的 service.proto 列表。loader 据此决定向外暴露哪些 service 和 type。

把两者分开的好处:

  • 加载的 service 一目了然,便于审计;
  • proto 的目录结构可以自定义,不影响加载。

获取目录

ESM 里 __dirname 不是全局变量,从 import.meta.url 派生:

import { ProtoLoader } from 'grpcity' import path from 'node:path' import { fileURLToPath } from 'node:url' const __dirname = path.dirname(fileURLToPath(import.meta.url))

Node.js >= 20.11 可以直接用 import.meta.dirname。CommonJS 下 __dirname 仍是内建全局。

加载单个目录

最常见的情形:一个 proto 目录里放多个 service 文件。

export default new ProtoLoader({ location: path.join(__dirname, './proto'), files: ['path/to/service-a.proto', 'path/to/service-b.proto'] })

加载多个目录

需要跨业务调用、proto 分散在不同目录时,传入数组:

export default new ProtoLoader([ { location: path.join(__dirname, './proto1'), files: ['path/to/service-a.proto'] }, { location: path.join(__dirname, './proto2'), files: ['path/to/service-b.proto'] } ])

初始化

init() 才真正去读取并解析 proto 文件,也是传入环境选项的地方,自然地放在服务启动流程的第一步。

await loader.init(options)

options 字段:

  • isDev:(可选,boolean)开关开发模式。本身不会产生任何外在效果,只用于启用 packagePrefix
  • packagePrefix:(可选,string)仅当 isDev: true 时生效。把加载到的所有 service 和 type 重新挂到 <prefix>.<原名>,wire 上的 gRPC 方法路径变成 /<prefix>.<package>.<Service>/...。适合做租户/环境隔离。
  • loadOptions:(可选,object)原样透传给 @grpc/proto-loader,按字段覆盖默认值。默认:keepCase: truelongs: Stringenums: Stringdefaults: falseoneofs: true

loadOptions 完整说明请见 Config

init()幂等并发安全 的:即使多个入口在首次 init() 完成前同时调用,它们也会共享同一个进行中的 promise。initServerinitClientsinitReflection 在你没调过的情况下会自动 init(),所以只有想传参或者想直接调用 service() / type() 时,才需要显式 await loader.init(options)

按环境选 prefix

使用 packagePrefix 时,服务端和客户端必须配同一个值——双方要在 wire 路径上达成一致。

test 环境:

await loader.init({ isDev: true, packagePrefix: 'test' })

stage 环境:

await loader.init({ isDev: true, packagePrefix: 'stage' })

生产环境:两个选项都不传。

await loader.init()
Last updated on