We highly recommend completing the tour to get an overview of
buf generatewith remote plugins.
Protobuf code generation is a challenging process for developers due to the complexities of working with protoc and plugins. This challenge is compounded as code generation is scaled across multiple developers, with different languages and runtime requirements for plugins.
To overcome these challenges, organizations and open-source projects often develop their own homegrown Protobuf tooling to simplify the developer experience and maintain consistent output. However, these solutions are often difficult to maintain over time, and knowledge of the solutions can be lost as staff leave the organization or project.
To provide a more streamlined approach to code generation, Buf's Remote Plugins remove the need for developers to manage, download, or run plugins on their local machines. This approach ensures a consistent environment and provides a necessary solution for the Protobuf ecosystem. Let's take a look at how you can simplify your code generation workflow with remote packages:
buf.gen.yaml file controls how the
buf generate command executes
Protobuf plugins for any input. Here, we can
specify remote plugins to perform code generation. For more
information on the
buf.gen.yaml configuration, see the
Buf verifies and maintains the commonly-used plugins used across the Protobuf ecosystem. To discover all publicly available plugins, go to buf.build/plugins.
1. Choose your input
Remote plugins generate code for inputs. An input
can be a git repository, tarball, zip file, a or local directory containing
Protobuf files configured with a
buf.yaml configuration file. Buf refers
to such directories of Protobuf files as modules.
For our purposes, we'll assume you have a
buf.yaml in your current directory
that defines a module. To create a
buf.yaml in your current directory.
$ buf mod init
version: v1 breaking: use: - FILE lint: use: - DEFAULT
See the build documentation for full details on how to
configure modules to build with
2. Create a
Now that you have an input to generate code for, we
need to define a
buf.gen.yaml and specify
protoc plugins you want to use.
A remote plugin can be pinned to a specific version, or if you want to always use the latest version of the plugin, the version can be omitted. Here's some examples for common languages and RPC frameworks:
version: v1 plugins: - plugin: buf.build/protocolbuffers/go out: gen/go opt: paths=source_relative - plugin: buf.build/grpc/go out: gen/go opt: paths=source_relative
Note, we're using the
plugin key to reference a remote plugin. More
information can be
found in the buf.gen.yaml docs.
Plugins are invoked in the order they are specified in your
results from each invocation combined before writing the result. For more
information, see the
As a best practice, when referencing remote, plugins we recommend including the version of the plugin to ensure reproducible code generation. It is possible to reference both local and remote plugins within a single template file.
3. Run generate
To generate using the module and
buf.gen.yaml defined in your current
$ buf generate
buf generate command will:
- Send the Protobuf files specified in your input to the Buf Schema Registry remote plugin executor.
- Invoke each plugin specified in your
- Send the results back, and unpack them on your local file system.
buf generate looks for a
buf.gen.yaml in your current directory. An
alternate location can be specified by usin the
$ buf generate --template templates/buf.go.gen.yaml
You can also run
buf generate. For example if all of your
.proto files are
# generate using the module defined in the foo/ directory $ buf generate foo # generate using the files contained in the root directory # of the github.com/acme/weather repository on the default branch $ buf generate https://github.com/acme/weather.git # generate using the buf.gen.yaml file at templates/buf.go.gen.yaml # using the files in the buf.build/grpc/grpc module $ buf generate --template templates/buf.go.gen.yaml buf.build/acme/petapis
If you used one of the example
buf.gen.yaml files from above, you should end
up with this file structure:
. ├── buf.gen.yaml └── gen └── go └── pet └── v1 ├── pet.pb.go └── pet_grpc.pb.go
4. Common use cases
message and enum stubs for Golang. The BSR hosts this plugin at
version: v1 plugins: - plugin: buf.build/protocolbuffers/go out: gen/go # You almost always want to set this option with protoc-gen-go opt: paths=source_relative
4.2. protoc-gen-go + protoc-gen-validate
protoc-gen-validate is a
plugin that generates polyglot message validators. The BSR hosts this plugin
pre-enabled for Go code generation at
version: v1 plugins: # The protoc-gen-go stubs are required for grpc-go - plugin: buf.build/protocolbuffers/go out: gen/go # You almost always want to set this option with protoc-gen-go opt: paths=source_relative - plugin: buf.build/bufbuild/validate-go # Make sure to generate your protoc-gen-validate code to the same # directory as protoc-gen-go out: gen/go # You almost always want to set this option with protoc-gen-go opt: paths=source_relative
generates Golang service stubs for gRPC. The BSR hosts this plugin at
buf.build/grpc/go. Note that we'd recommend
checking out connect-go instead of using grpc-go (see the next section).
version: v1 plugins: # The protoc-gen-go stubs are required for grpc-go - plugin: buf.build/protocolbuffers/go out: gen/go # You almost always want to set this option with protoc-gen-go opt: paths=source_relative - plugin: buf.build/grpc/go # Make sure to generate your grpc-go code to the same # directory as protoc-gen-go out: gen/go # You almost always want to set this option with protoc-gen-go-grpc opt: paths=source_relative
Connect-Go is a slim library for building browser and gRPC-compatible HTTP APIs. Handlers and clients support three protocols: gRPC, gRPC-Web, and Connect's own protocol.
Golang service stubs for Connect. The BSR hosts this plugin at
version: v1 plugins: # The protoc-gen-go stubs are required for grpc-go - plugin: buf.build/protocolbuffers/go out: gen/go # You almost always want to set this option with protoc-gen-go opt: paths=source_relative - plugin: buf.build/bufbuild/connect-go # Unlike grpc-go, connect stubs do not need to be generated to the # same directory, however you are free to do so out: gen/go # You almost always want to set this option with protoc-gen-connect-go opt: paths=source_relative
Connect-ES brings the Connect ecosystem to TypeScript, the web browser, and to Node.js. It contains packages for working with Connect and gRPC-Web clients from the browser as well as Connect-, gRPC-, and gRPC-Web-compatible clients and servers in Node.js
protoc-gen-es plugin to generate
message and service stubs. The code generated by these two plugins requires the
The BSR hosts these plugins at buf.build/bufbuild/connect-es and buf.build/bufbuild/es.
version: v1 plugins: - plugin: buf.build/bufbuild/es out: gen/es - plugin: buf.build/bufbuild/connect-es out: gen/es
Connect-Swift is a small library that provides support for using generated, type-safe, and idiomatic Swift APIs to communicate with your app's servers. It can be used with both the gRPC-Web and Connect protocols.
is responsible for generating Swift clients, and relies on the models generated
The BSR hosts both of these plugins at
and buf.build/apple/swift, respectively.
To get started with Connect-Swift, check out the demo tutorial.
version: v1 plugins: - plugin: buf.build/apple/swift opt: Visibility=Public out: gen/swift - plugin: buf.build/bufbuild/connect-swift opt: Visibility=Public out: gen/swift
Code generation with Protobuf can be a complex and challenging process, which becomes more difficult when scaling to multiple developers. Remote plugins are the answer. Buf's remote plugins offer a streamlined approach, removing the need for local management and maintenance.
If you're interested in learning more about code generation with Protobuf, or how Buf can help streamline your development process, be sure to check out Supercharging your project with Remote Packages