Pular para o conteúdo

gRPC-Web com Golang e VueJS: Uma alternativa ao REST e GraphQL

Postado em 4 minutos de leitura

gRPC-Web é uma biblioteca JavaScript que permite a comunicação direta entre front-end e back-end sem precisar de um servidor HTTP intermediário.

Com o gRPC-Web, você pode facilmenete criar um aplicação com arquiterura gRPC de ponta-a-ponta ao definir os tipos de dados e seriços com Protocol Buffers.

gRPC é um sistema de chamada de procedimento remoto (RPC - Remoce Procedure Call) rápido e eficiente que permite que microserviços se comuniquem. Você pode aprender mais sobre gRPC na documentação oficial ou em outro artigo que eu escrevi com o título Building microservices in Go and Python using gRPC.

gRPC-Web, tal como gRPC, permite que seja definido um "contrato" de serviço entre o cliente e o servidor usando a estrutura protobuf. Você cria a definição dos tipos de dados, o nome dos serviços e os valores que eles recebem e retornam, utilizando Protocol Buffers, e depois utiliza o compilador protoc para gerar o código necessário para a comunicação entre front-end e back-end. Esse processo de desenvolvimento evita a necessidade de ter que lidar com coisas como lógica de serialização e deserialização de JSON, status code do HTTP, content-types, headers etc.

Vantanges de usar gRPC-Web

  • gRPC de ponta-a-ponta: O cliente pode interagir diretamente com um ou mais servidores gRPC apenas chamando as funções definidas.
  • Proximidade entre equipes de front-end e back-end: Utilizando Protocol Buffers para definir todos os serviços, a interação entre front e back é apenas mais uma camada gRPC. O contrato entre front e back é conhecido e o código do cliente pode ser regerado quando houver alguma mudança no contrato.
  • Facilidade para gerar bibliotecas de cliente: Não precisa importar bibliotecas de terceiros como axios. O código gerado pelo compilador protoc pode ser importado para qualquer cliente.

Exemplo de uma aplicação gRPC-Web

Eu comecei criando o arquivo de definição accounts.proto simples como esse:

syntax = "proto3";

package private;
option go_package = "proto";

service AccountService {
    rpc Create(User) returns (User) {}
    rpc AuthenticateByEmailAndPassword(User) returns (Account) {}
}

message User {
    string email = 1;
    string password = 2;
}

message Account {
    string token = 1;
}

message Nothing {}

Então eu executei os comandos abaixo para gerar os códigos do servidor e do cliente:

protoc -I proto proto/*.proto --proto_path=./proto --go_out=plugins=grpc:./backend/proto
protoc -I proto proto/*.proto --js_out=import_style=commonjs:./frontend/proto --grpc-web_out=import_style=commonjs,mode=grpcwebtext:./frontend/proto

O comando acima cria o arquivo frontend/proto/accounts_grpc_web_pb.js contendo a implementação dos serviços e o arquivo frontend/proto/accounts_pb.js contendo a definição dos tipos de dados.

Depois disso, eu implementei um código em Go e a chamada ao serviço em Javascript. Abaixo um exemplo mais ou menos do código que está no GitHub:

import (
    ...
    pb "backend/proto"
)

func (instance *AccountServer) Create(ctx context.Context, req *pb.User) (*pb.User, error) { 
    user := structs.User{
        Email:    req.Email,
        Password: req.Password,
    }
    query := `INSERT INTO accounts (email, password) VALUES (:email, :password);`
    conn := instance.db.GetConnection()
    _, err := conn.NamedExec(query, &user)
    return &pb.User{Email: user.Email}, err
}

E chamei a função gRPC create no Javascript:

import { Account, User } from '../../proto/accounts_pb'
import { AccountServicePromiseClient } from '../../proto/accounts_grpc_web_pb'

export default class {
    constructor () {
        this.client = new AccountServicePromiseClient('http://localhost:9000', null, null)
    }

    async create (user) {
        const req = new User()
        req.setEmail('me@gustavohenrique.com')
        req.setPassword('verystrongpassword')
        try {
            const res = await this.client.create(req, {})
            return res.getEmail()
        } catch (err) {
            console.error(err.message)
            throw err
        }
    }
}

O código completo escrito em Golang e VueJS (usando Quasar Framework) pode ser encontrado nesse repositório.

Conclusão

Agora você deve estar se perguntando "Eu devo utilizar gRPC?"

gRPC é arquitetura robusta que possui vários apoiadores. Empresas como Google, Netflix e Dropbox já utilizam em produção. Por ter uma baixa curva de aprendizado, novos desenvolvedores em um projeto gRPC conseguem ser produtivos rapidamente. A definição dos tipos e serviços em Protocol Buffer funciona como uma documentação também - quem for consumir o serviço consegue saber o que deve enviar no request e o que pode ser recebido no response.

gRPC-Web é uma excelente opção para desenvolvedores da web. Ele traz portabilidade, excelente performance e um protocolo sofisticado para uso no front-end web ou mobile.