最近のフロントエンド、ぶっちゃけどうですか?

tadano:本日はpotato4dでおなじみの花谷さんと、kahirokunn。フリーランスなんですよね?

kahirokunn氏(以下、kahirokunn):そうです。

tadano:活躍されているエンジニアのお二人をお招きいたしまして、トークセッションをやらせていただこうと思います。テーマは「最近のフロントエンド、ぶっちゃけどうっすか?」。めっちゃ話し言葉ですね(笑)。花谷さんが考えたタイトルですね。

potato4d氏(以下、potato4d):そうですね(笑)。

(一同笑)

tadano:さっそく自己紹介をお願いします。

potato4d:花谷拓磨と申します。LINE株式会社のフロントエンドエンジニアで、フリーランスも継続中です。メインはフロントエンドエンジニアですが、Webエンジニアもやっています。

うちの会社が中心でやっている「UIT」というフロントエンドのイベントのオーガナイザーなので、興味があるという方は、応募したり調べたりしてもらえればと思います。よろしくお願いします。

(一同拍手)

kahirokunn:フリーランスでやっている、kahiroといいます。最近はVue.jsをやっています。よろしくお願いします!

(一同拍手)

tadano:Qiitaには「設計ちょっとできる」とか書いてますよね。

kahirokunn:あー……ヤバい(笑)。

potato4d:それでいうと、この2人はQiitaのVue.jsタグのワンツーですよ。上位独占組です。

tadano:へぇー! 今日呼んでよかった。

(一同笑)

tadano:後ろの2人は、MCの田口と、めるさんです。よろしくお願いします。

(一同拍手)

最近の技術スタックどんな感じですか?

tadano:じゃあ、さっそく本題に移ります。Q1.「最近の技術スタックどんな感じですか?」。なにか言いたいことや特別なこと、ありますか?

potato4d:自分がそうだからかもしれないので、特別かはわかりませんが。自分の仕事範囲だと、今、フロントエンド開発では、Vue.jsのコンテキストでのNuxt.jsの開発がすごく多いと思っています。

もちろん、SPAの開発の生産性向上のツールとしてNuxt.jsが使われていることも、SSR用に使われていることもあるんですけど。今、仕事でただのVue.jsを使う機会はほとんどないということが、特徴としてある気がします。kahiroさんはどうですか?

kahirokunn:自分がメインで開発する場合は、Nuxt.jsに乗っからないで、ただのVue.jsでやることが多いです。クライアントさんは、ただのVue.jsの場合とNuxt.jsのSPAの場合、両方ありますね。

tadano:フレームワークだとNuxt.js、Vue.jsで。花谷さんは、Vue.js単体で使うことはあまりない。

potato4d:最近は、あまり単体では使わないと思います。

tadano:kahiroさんは、受注とかフリーランスで活動されていると、スポットでVue.jsを使うことがわりとある感じですかね。

kahirokunn:そうですね。お手伝いでうかがうときは、向こうがただのVue.jsでやっている場合はそれに従うことになるので。

tadano:なるほど。そういう場合、ES6以降やTSを使うみたいな言語の問題は、最近はどういうスタックですか?

kahirokunn:自分は基本的に、ES6といわず7、8と、上げられるところまで上げています。TypeScriptも使いたいので導入はしているんですが、Vue.jsのバージョンによってはTypeScriptの書き心地がそこまで良くないこともあるので、そういった場面はなるべくただのESで収められないか模索します。代わりにコードはシンプルに、型の力がそこまでいらなくても開発しやすい構造でやるよう努力しています。

tadano:今kahiroさんが「型で逆に開発をしづらくなる場合がある」という感じでおっしゃいましたが、花谷さんはなにか思うところなどありますか?

potato4d:最近、本業はSPA班みたいな仕事ですけど、副業もちょこちょこやっているんですね。Nuxt.jsが、2.4ぐらいから徐々にTypeScriptサポートを強くしてきているので、Nuxt.js/TypeScriptで開発したいという顧問や技術相談をけっこう受けるんです。

なので「やってみたい」というモチベーションはあると思うんですけど、TypeScriptを入れたからといって、現場の全員がついていけるわけでもないとは感じています。

TypeScriptを入れたがる人はめちゃめちゃ多いけど、厳格に運用しようとすると枷になりやすいのかなと、いろんなところで話を聞いていて感じますね。

うちの場合、古いESで書くプロジェクトはもうほぼないんです。純粋な、Nuxt.jsに乗っているという理由もありますし、基本的には最新のES Nextで使える範囲は全部使えるんですけど。TSにするかどうかは現場によりけりで、その都度判断しています。

現場の型リテラシーが二分化されている

tadano:そのチームがTSに順応できるかどうかのレベル感を計って、導入するかどうかを決める感じですか。

potato4d:そうですね。このへんはkahiroさんとも議論したい内容です。自分も以前フリーランスでやっていましたが、現場の型リテラシーって、二分化されていると思うんです。

特定の技術をディスるわけではないけど、Laravel文脈とかRails文脈みたいな、いわゆるLLでずっと開発してきている人は、そもそも静的型付けの知識が薄い。

例えばジェネリクスとかもなにもない、Cとか教本でやったJavaとかの「柔軟に型の取扱いをするんだったら、わざわざメソッドをたくさん型ごとに書かないといけないんでしょ」から入るような現場だと、けっこうつらい。

だから裏で使っている技術とかも加味して導入の可否を検討するんですが、kahiroさんはそのへんどうですか。

kahirokunn:間違いなくありますね。ただし自分としては、エンジニアであれば、ある程度コストを払っても型リテラシーはつけるべきだと思っています。型とかそもそものプログラムの構造、どういったコードを書けば、どういった制約があれば、単体テストを減らせて、プロダクションで動くアプリケーションのバグやエラーを減らせるか、という知識をつけるべきでしょうね。

もともとの型リテラシーが少ないとコストがかかるかもしれないけど、払うコストより得られる効果のほうが大きいと思っています。

tadano:コストというのは、型システムを導入して学んでいくことですか。

kahirokunn:そうですね。ただし一発目から本プロジェクトに導入するわけではなくて、サイドプロジェクトから少しずつ、社員の型リテラシーとか知識を段階的に向上させる取り組みをできないか、と模索しています。「クライアントさん、そういうやつなにかない?」って(笑)。

(一同笑)

tadano:いろいろありそうですね(笑)。

kahirokunn:例えば、Chrome Extentionをちゃんと作ってみる。

tadano:あぁー。

kahirokunn:「TypeScript、やってみません?」という提案は、すごく良いと思います。

tadano:ということは、お二人とも最近の業務はそういう相談が多い感じですか?

potato4d:自分はそうですね。表面的な部分でいうと、ではありますが。

tadano:なるほど。

『がんばらないTypeScript』のインパクト

potato4d:ただ最近、gfxさんという有名なエンジニアの方が『がんばらないTypeScript』という記事を出しました。

あれだけTSに慣れている人があえて「がんばらない」と言ってくれたことで、そこまで厳密な型定義をしなくても開発自体はやっていけるんだという、導入の足がかりになる情報が増えてきたんですね。

「お前がそう思ってるだけだろ」ではなくなってきたので、相談を受けたときも回答しやすくなった(笑)。界隈の総意として「ゆるくやるのもアリなんじゃない」という方向性が出てきたことは、わりとすごい進歩だと感じています。

tadano:巨人の肩に乗る、でもないですが、重鎮がそう言ってくれるとありがたいですよね。今日はVue.jsの勉強会ですけど、Vue.js以外でもなにかあったりしますか?(笑)。

(一同笑)

potato4d:今「型を書くと単体テストが楽になる」という話をしていましたが、そもそもどの現場もちゃんとテストを書いているのかどうかが気になります(笑)。

kahirokunn:そうですね。一切書いていない現場と、めっちゃ書いている現場がありますね。TypeScriptを導入しているかどうかは関係ないです。

tadano:「TS導入しただけでテストが減る」という意見をたまに聞きますけど、本当ですか? そういう実感ありますか?

kahirokunn:自分は、間違いなく減っていると思います。例えば、与えられたパラメータがInt以外、整数型じゃなかったらリターンとか、stringじゃなかったらリターンというコードがたまに書かれているんですど、自分はそういうものを絶対に関数内に入れたくないんですね。

型システムが導入されていれば、そもそもそういうコードが入ってこないので入れる入れないの議論が減るし、そういった些細なエラーが減る。型システムによって、どういったデータが流れてくるかをある程度保証できるということですね。

tadano:JSで書かれたコンポーネントで、propsとかで型は指定できますけど、それとは比にならないくらい、もっともっと型が恩恵を受けられる感じですか。

kahirokunn:そうですね。型はすごいです。

tadano:でも、それってVue.jsだけの話でもなくて、もっと広義のところですよね。TypeScriptの話というか。

potato4d:今の話はどちらかというと、propsで困るところって「object」って書いてあるところが、validatorを自分で書かないと厳密に書けないというところですね。うまさもありますが。

Vue.jsの場合はSFCで書かれていることがほとんどなので、そのへんの問題はあんまり根本的な解決にはならない。例えばpropsで渡すときは、親側のコンポーネントで型が合っていなくても、あんまりエラーは出てくれないので。

今の話はどちらかというと、例えばmethodsに定義しているものの型不整合とかを防ぎやすいとか。テストコードだけじゃなくて、アプリケーションコードのガード式みたいなものを減らしていけるというところが、メリットとしてある気がします。

tadano:なるほど。

potato4d:そのへんだと、まだVue.jsのテンプレートとくっついた型は弱いイメージですが、どうですか。

kahirokunn:そうですね、テンプレートとくっついた型はめちゃくちゃ弱いと思っています。

potato4d:そうですよね。

kahirokunn:三大フレームワーク以外にもいろいろ触っていますが、Vue.jsは残念ながらそこの競争には負けています。でも、次期Vue.jsとか、あとで話しますがVue function-based APIとかが解決するかもしれないと思っているので、すごく期待はしています。

potato4d:なるほど。

気になるフロントエンドの動向

tadano:Q2.「気になるフロントエンドの動向ありますか」。

kahirokunn:自分はwasmです。

tadano:その心は?

Kahirokunn:「素早い」「ポータビリティがある」「軽量」ですね。

tadano:すごくつらそうなイメージがありますけど、書きやすさはどうなんですか。

kahirokunn:watという、wasmのバイナリにコンパイルできるネイティブな記法があって、それで書くとつらい部分はあります。しかし、例えばRustとかほかの言語を使うと、wasmにコンパイルできて、しかもそのままwasm-bindgenとか、いろいろ使うとラッピングしてくれるライブラリをRustが提供してくれているので、それを使えば、まるでJSの関数のように簡単に呼べる。

例えば、勉強用にFirebaseで三目並べを作ったんですね。AIの部分はミニマックス法で、Rustで書かれています。それをそのままwasmで排出して、Vue.jsに乗せてみたら一瞬で乗っかりました。書き心地は悪くなかったです。

基本的にwasmのニーズは、ロジックがゴリゴリ入っていて、かつ高速な部分だと思うんですが。そういった部分はもっとそれに向いている言語で書くという選択肢も取れるので、すごくいいなとは思っています。あと、Web以外でも動かせる可能性がある。

tadano:例えばどこのプラットフォームで動くんですか。ネイティブ?

kahirokunn:ネイティブとか、wasmを動かす環境さえあればローカルでも動かせます。グーグルさんのDartが、がんばってサポートしているという噂が聞こえてたりするので、そういう動向が出てきているみたいです。

potato4d:ちなみにwasmでいうと、普通にコマンドラインでも使われる用途があって。wasmでnginxを動かせる、みたいなプロジェクトもあります。けっこうおもしろいので、後ほどTwitterで呟いておきますね。

私が今フロントエンドで気になっているやつは、最近副業のほうで導入しようとしているんですが、gRPC-webをめちゃめちゃ推していますね。

kahirokunn:あー。

言語に依存しないgRPC

potato4d:今回会場にお越しいただいている方はフロントエンドの人が多いと思うので、もしかしたらgRPCにはなじみがないかもしれませんが。

gRPCはプロトコルバッファといって「言語に依存しない型定義ファイル」みたいな、いわゆるGraphQL的なものですね。GraphQL的なデータのモデリング定義をしてしまって、それをもとにしています。具体的には、マイクロサービス同士の通信などで使われています。やり取りするデータの型を定義して、その型定義だけを信じてお互いに実装して通信していく、というプロトコルライブラリです。

それのWeb実装が去年の夏ごろ、ついにバージョン1.0とかGAして、Stableになっていっている。個人的には推しています。

tadano:ブラウザ上で動くんですか?

potato4d:ブラウザ上で動きます。とはいえ、内部的にはTCP通信が行われますが、ブラウザ側にgRPCの通信プロトコルはないので、内部的にはXHRとかに置き換わって、ただ互換性のあるリクエストが飛ばせるというかたちですが。

そういうかたちで送信することで、もともとマイクロサービス間みたいな、メインのサービスとそれに従属するサービスが通信するときに使っていたプロトコルバッファからTSの型定義とかを吐けるので、そのままフロントエンドにも流用できて、タイプセーフかつパフォーマンス的にも優れた通信が取れるんです。それが今、おもしろいと思っています。

kahirokunn:自分の場合、Webソケットでフロントとサーバーをつないで、全部その上で喋ったらめちゃくちゃ速いんじゃないかと思ったんですけど。gRPC-webの場合、HTTP/2がサポートされてる端末だとその上で喋ってくれると聞いたんですが、そうしたらめちゃくちゃ高速でいいじゃないですか。

potato4d:そうですね。

kahirokunn:代わりにgRPC-webを使った場合の、サーバーサイドレンダリング系のWebのスタックはどうなるんだろう、とちらっと思ったんですが(笑)。そのへんはどうですか?

potato4d:すごくわかります。今もそこは「どうしようかな」という段階です。そもそもgRPCはHTTP/2がデファクトの世界感みたいな感じなのでパフォーマンスにも優れるし。要は、マイクロサービスはめちゃくちゃ通信するので、普通のhttp1.1ではまかないきれない部分をHTTP/2でやれるというところはすごくいい。

とはいえ、そもそもgRPC-webは結局XHRになっちゃうので、実は1.1でもリクエストできてしまうんです。なのでそこは気をつけないといけないんですが、そのへんのHTTP/2は魅力だと思います。

ただこれからやっぱりSSRも出てきますし、たくさんBFF層とかが重なってくる中で「これ、どれだけ妥当なんだっけ」というところは、まだ試し打ち状態です。ぶっちゃけると「えいや」でプロダクトに入れてしまえ、という状態です。

kahirokunn:(笑)。

potato4d:どこまで耐えうるか、どこまでスケールするかはわからないけど、期待が持てる感じです。とくにSSRサーバーとかの場合、結局後ろはノードサーバーが走っているので。最悪、普通のgRPCのライブラリを使うこともできるので。インジェクションしてやって作るという術もなくはないので。

ひとまずはIDLによる通信、プロトコルバッファによる通信が担保されていけば、幸せになれるんじゃないかという気はしていますね。まぁ「GraphQLでいいじゃん」と言われたら「そうかもしれない」としか言えないけど(笑)。

(一同笑)

kahirokunn:GraphQLも魅力的ですよね。gRPCとはまた違った特徴とおもしろみがある。なかなか選べないですね。

potato4d:gRPC-webはシンプルな通信プロトコル感がありますけど、GraphQLはフロントエンドが柔軟にリクエストを受けるためにサーバーがめっちゃがんばる、という気がする。内部のリソースを都合したいかな、という気がしますね。

kahirokunn:そうですね。