12
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Vue+ProtocolBuffers+TypeScriptでサーバー側APIとの連携がやりやすくなった。

Last updated at Posted at 2018-11-02

概要

Vueで開発中のアプリにTypeScriptを導入し、サーバー側とのやり取りをJSONではなく、Protocol Buffersにしたところ、
サーバー側APIのインタフェース変更に強くなり、開発が柔軟になった。

登場人物の紹介

Vue

モダンなJavaScriptフレームワーク。もともとAngular4とかは触ったことが合ったが、それに比べて規約がゆるく柔軟に書きやすい感じはあった。
ただAngularのTypeScriptで書く感じに慣れていると、型がないことによる実行時のエラーが何かモヤっとする。

TypeScript

AltJS。JavaScriptに型がつけられる、しょうもないミスを減らせて嬉しい。油断するとすぐanyにしてしまう。

Protocol Buffers

.protoというファイルでインタフェースを定義し、言語に合わせてトランスパイルすることで、
フロントエンド/バックエンドのインタフェースを一つのファイルで定義することができる。

定義内容

message Person {
  required string name = 1;
  required int32 id = 2;
  optional string email = 3;
}

フロント<->サーバーのデータやり取りで一番多いフォーマットはJSONだと思ってますが、
JSONの難点として、サーバー側のインタフェースの変更があったときに気づきにくいというのがあります。
解決手段として、SwaggerによってAPIを定義していくというのもありますが、アプリ開発時にProtocol Buffersを利用したところ非常に便利だったので、
Webでもやりたいなーということで探したところ、protobuf.jsというのが存在したので利用してみることに。

Protocol Buffersの組み込み方

  • サーバー<->アプリのAPIのインタフェースとして.protoファイルを定義する
message User {
  int32 id = 1;
  string name = 2;
}
  • サーバー用(今回はPHPでした)とフロント用のインタフェースを生成
pbjs -t static-module -w commonjs -o compiled.js user.proto
  • TypeScriptから型定義を扱えるようにするため、.d.tsファイルを生成
pbts -o compiled.d.ts compiled.js

あとは生成されたjsと.d.tsを組み込むだけ。

axiosを利用した利用方法

VueのHttpClientと言えばaxiosという感じなのでAxiosからの利用方法。
Protocol Buffersは通信自体はバイナリで行われるので、axiosでResponseを受け取ったあとにdecodeしてやる必要があります。

axios.get('/user',{
  transformResponse:[function(data: any){
    return User.decode(data) // バイナリであるdataをUser型にdecodeしている
  }]
}).then(user =>{
  console.log(user.name)
})

これでUserデータが型のついた状態で扱えるようになります。
サーバー側も同様のprotoファイルから生成された型を通信で利用している限り、繋いだときのインタフェースのミスは起きにくくなります。
protoファイル上でプロパティ名が変更になった際も、.protoファイルを再度transpileすることで、
プロパティが変わった場所はコンパイルエラーになるため、実行時エラーも未然に防ぐことができます。

Vueで更に便利に利用するためには

VueとTypeScriptは実はあまり相性が良くありません。
というのも、コンパイルエラーはVueのtemplateの中まで見てくれないため、protoで生成された型を直接template内部で利用していた場合は、その部分が実行時まで分からなくなってしまうんですね。

<template>
<div>
{{user.id}} // ここでプロパティ名を間違えていてもTypeScriptのコンパイラが検知してくれない
</div>
</template>

解決策として、Vue側でテンプレートを利用せず、描画関数を利用したtsx記法で書くことができます。
tsxは基本TypeScriptの糖衣構文なので、コンパイルエラーで検知することができます。

@Component
export default class UserComponent extends Vue  {
  render() {
    return(<div>{user.id}</div>) // TypeScriptの世界なのでコンパイルが検知する
  }
}

まとめ

  • TypeScript + ProtocolBuffersを導入することで、サーバー側のAPI変更の取り込みが容易になる。
  • Vue + TypeScriptの場合はTSX記法を利用することで、より型の特性を強力に支えて便利

そんな感じです。

12
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?