DEV Community

Cover image for A TODO app using grpc-web and Vue.js
J Aravindhan
J Aravindhan

Posted on

A TODO app using grpc-web and Vue.js

gRPC an introduction

gRPC is an open source, modern RPC framework initially developed at Google. It uses protocol buffers as an interface description language, protobuf is a mechanism for serializing structured data. You just define your services and its data structure in the proto file and gRPC automatically generates client and server stubs for your service in a variety of languages and platforms. Using profobuf allows us to communicate using binary instead of JSON, this makes gRPC much faster and reliable. Some of the other key features of gRPC are bidirectional streaming and flow control, blocking or nonblocking bindings and pluggable authentication. gRPC uses HTTP/2 which uses multiplexing by which client and servers can both initiate multiple streams on a single underlying TCP connection, You can read more about gRPC here.

gRPC-web

gRPC-Web is a javascript library using which we can directly talk to the gRPC service via web-browser. gRPC-Web clients connect to gRPC services via a special gateway proxy(Envoy proxy) which is going to be a docker service in our case running on the same server machine which bridges GRPC( HTTP/2) with Browser Communication (HTTP/1.1)

This was the game changer because initially we were able to use gRPC only for communications between services or micro-services and the client can only use REST API calls to access the data, but now by using the gRPC we can make use of the power of gRPC throughout our app and eliminate REST

Why gRPC is better than REST

The major differences between REST and gRPC are

REST meme

  • Payload type, REST uses JSON and gRPC uses Protobuff
  • Transfer protocol, REST uses HTTP/1.1 and gRPC uses HTTP/2

Since we are using Protobuf in gRPC we don't have to care about the verbs(GET, PUT) and headers etc. Also, it reduces the serialization code which we have to write for all the data models the stubs generated by the gRPC framework takes care of these.

Since we are using HTTP/2 in gRPC now we can stream both request and response and get rid of latency issues, Head of line blocking and complexity in establishing TCP connections.

Required tools and software's

  • Protoc v3.6.1— Protobuf compiler to generate client and server stubs.
  • go v1.11 — Our server is going to be built using go lang.
  • NodeJS — To build the Vue.JS frontend app.
  • Docker — To run envoy proxy.

Folder structure

Folder structure

An overview of topics to be covered

  1. Creating a proto file
  2. Creating server stubs and writing gRPC service handlers
  3. Creating gRPC service
  4. Creating Envoy proxy service
  5. Creating client stubs and client application

1. Proto file

Okay now let's jump into the code, the proto file is the heart of our gRPC app using this file the gRPC framework generates the client and server stubs, we define our data models and the services which are going to consume those data models, this file will be placed inside the todo folder at the root of our project.

The first line of the file specifies the version of the proto-buffer we are going to use, the same package name we specified in the second line will also be used in the generated go file. In our todoService we have three RPC methods addTodo, deleteTodo, getTodos with its request types as arguments and response types as the return type of the RPC method. On each message type we specify tags like=1, =2 which are unique tags which will be used at the time of encoding and decoding. The repeated keyword means that the field can be repeated any number of times.

2. Generate server stub file

Next step after creating our proto file is to generate the server stubs using which we will create our gRPC server. We are going to use protoc to generate the stub files, use the below command from the root of the project

protoc -I todo/ todo/todo.proto --go_out=plugins=grpc:todo

In the above command, we specify our output folder to be todo/ and the input file to be todo/todo.proto and we specify the plugin name and the package name for the generated stub file. after executing the above command you can find a new file named todo.pb.go inside the todo folder.

Now we have to write handler methods for all our RPC methods specified in the proto file, we will be creating a new file handler.go inside the same todo folder.



For the sake of simplicity, I am not going to use any database for storing and retrieving our todo’s, Since we are in the same generated todo package I can use the request and response data types from the generated stub files. All our handler methods are tied to the server struct.

In addTodo handler function, I am using a UUID package to generate a unique ID for every todo’s and generate a todo object and append it to the Todos list in the server struct

In the GetTodoshandler function, I am just returning the Todos list inside the server struct.

In the deleteTodo handler function, I am just doing an find and delete operation using the todo id and updating the Todos list in the server struct.

3. Hook up the gRPC server

Now we have to hook up all the handler and start the gRPC server, we are going to create a new file server.go in the root of our project.


In the above file, we are creating a new server at port 14586 and an empty todo server instance and a new gRPC server, we are using the RegisterTodoServiceto register our todo service with the newly created gRPC server then we serve the created gRPC server.

To run the above file use go run server.go from the root of the project which will start the gRPC server.

4. Envoy proxy setup

Envoy proxy is going to be a docker service which will be sitting in between our server and client apps, below are the envoy proxy docker and config files.



Our todo gRPC service will be running at port 14586 and Envoy will be intercepting HTTP 1.1 traffic at 8080 and re-directing it to 14586 as HTTP2(GRPC)

To build the Docker container

sudo -E docker build -t envoy:v1 .

To start the envoy proxy start the docker container using

sudo docker run  -p 8080:8080 --net=host  envoy:v1

5. Vue.js frontend app

Now the only missing part is the client, we are going to use Vue.js framework to create our client web application, for the sake of simplicity we are only going to look at the methods which are responsible for adding and deleting the todos.

Create a Vue.js project using vue-cli

vue create todo-client

This creates a new folder named todo-client in the root of our project next we have to create the client stubs

Use the below command to create the client stubs

protoc --proto_path=todo --js_out=import_style=commonjs,binary:todo-client/src/ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:todo-client/src/ todo/todo.proto

The above command will create two files todo_pb.js and todo_grpc_web_pb.js in the src folder. For the sake of simplicity, I am only going to cover the parts where gRPC service client is used

import { addTodoParams, getTodoParams, deleteTodoParams } from "./todo_pb";
import { todoServiceClient } from "./todo_grpc_web_pb";

In the todo component of our client app import all the required data types from todo_pb.js and the client from todo_grpc_web_pb.js we then create a new client instance using todoServiceClient and use the localhost URL with the port which we configured our envoy proxy to listen as the server URL and save the client instance.



Above are the methods hooked up to the components add todo button click and delete todo icon click. We are just using our client stubs to execute our gRPC services and use the stub datatypes and it’s setters and getters to handle the data to be sent/received from the server.

Client app demo

Conclusion

Thank you for taking the time to read this till the end😁, If you have any queries regarding this or something I should add, correct or remove, feel free to comment below.

If you really enjoyed reading it don't forget to press the clap icon

You can find the full source code at this repo, and follow me on GitHub and LinkedIn

Originally published at Medium

Top comments (1)

Collapse
 
dasdaniel profile image
Daniel P 🇨🇦

looks like the proto file is missing

for context, here it is from the medium link

syntax = "proto3";
package todo;

message getTodoParams{}

message addTodoParams {
  string task = 1;
}

message deleteTodoParams {
  string id = 1;
}

message todoObject {
  string id = 1;
  string task = 2;
}

message todoResponse {
  repeated todoObject todos = 1;
}

message deleteResponse {
  string message = 1;
}  

service todoService {
  rpc addTodo(addTodoParams) returns (todoObject) {}
  rpc deleteTodo(deleteTodoParams) returns (deleteResponse) {}
  rpc getTodos(getTodoParams) returns (todoResponse) {}
}