A protoc
plugin to generate JavaScript code from .proto
files along
with TypeScript declarations.
It is intended as a faster replacement for protobufjs-cli
, ideal for
large, evolving projects with many protos. The generated code uses
protobufjs/minimal
and long
as the only runtime dependencies.
-
Generates code 10X faster. One benchmark run on https://github.com/buildbuddy-io/buildbuddy brings the code generation time from ~19s to ~1.8s.
-
Supports generating code for only a single
.proto
file and not its imported files1. This makes it a good fit for build systems like Bazel which are optimized for many small build steps rather than a few big build steps. -
Imports are declared explicitly, rather than referencing global "roots". This makes it easier to navigate the generated code.
-
Generated code preserves comments from the original proto source.
The generated code is compatible with pbjs
+ pbts
, where pbjs
is
run with the following flags:
--target=static-module
--wrap=es6
--force-message
--strict-long
--no-delimited
--no-verify
(PRs are welcome to add support for other options that would increase compatibility with the protobufjs-cli.)
In addition, the generated code is incompatible in the following ways:
- Does not support the deprecated proto2 groups feature
- Does not yet support proto2
default
value annotations - Does not generate
_optional
getters for proto3 optional scalar fields; instead types the field as|null|undefined
- Does not support reflection
- Does not support register global
protobuf.roots
entries likeprotobuf.roots["default"].my.proto.Message
# Install the plugin
go install github.com/buildbuddy-io/protoc-gen-protobufjs@latest
# Make sure the installed binary (protoc-gen-protobufjs) is in $PATH
export PATH="$(go env GOPATH)/bin:$PATH"
# Compile your protos
protoc --protobufjs_out=./out ./src/hello.proto
The plugin supports the following flags:
-import_path: PROTO_PATH=TS_PATH
A mapping of proto imports to TS imports, as PROTO_PATH=TS_PATH pairs
(this flag can be specified more than once). If the proto does not end
with '.proto' then these act as directory prefixes.
-out: path
Output file path. If this is set and multiple protos are provided as
input, the generated code for all protos will be written to this file.
Any '.ts' or '.js' extension will be ignored.
-strict_imports:
If set, all directly imported protos must have an -import_path
specified. This is useful when integrating with a build system where all
direct dependencies must be explicitly specified.
-import_module_specifier_ending: string
Suffix to apply to generated import module specifiers. May need to be
set to ".js" in rare cases.
Flags are specified using the --protobufjs_opt
flag to protoc
. To
specify multiple plugin flags, separate each flag with ":" (note that
passing --protobufjs_opt
more than once will not accumulate flags).
Example:
protoc \
--protobufjs_out=./out/ \
--protobufjs_opt=-strict_imports:-import_path=src/foo.proto:src/foo.ts
Footnotes
-
By default,
protobufjs-cli
bundles all transitive dependencies into the output.js
file, which causes an explosion of unnecessary dependency edges in the build graph.protobufjs-cli
does have a--sparse
option, but this only excludes indirect imports from the output JS. For example, let's say we havea.proto
that importsb.proto
, andb.proto
importsc.proto
. Thenpbjs --sparse a.proto
generates code for both A and B in the output. Withprotoc-gen-protobufjs
, the generated code only contains A, and instead generates an import for B. ↩