TypeScriptを使ったWebアプリ開発のよかったところと反省点
2020-12-19
azblob://2022/11/11/eyecatch/2020-12-19-webapp-development-using-typescript-reconsideration-poem-000.jpg

本記事はFIXER Advent Calendar 2020( https://adventar.org/calendars/5752 )の記事です。
弊社ではなんとカレンダーを3つも立てるということで、みなさん気合が入った記事を書いてらっしゃるので是非ともご確認ください!

前回はTakumi Satoくんの「Visual Studio CodeでC#開発環境整えちゃう(Goodbye Visual Studio)」という記事です。
過去.NETのコードを実行したり、ちょっと触る機会があったのですが、その時普段Visual Studioを使用していなかったため大変重宝しました。
VSCode便利。

今回は年の瀬ですので弊社内で開発をしていたサービスについてまとめ的に技術面、開発面でよかったこと、むずかしかったところを個人的な観点でまとめていこうかなと思います。
今後当該のフレームワークを使う予定のある方だけでなく、別のフレームワークを使って開発している方にも参考になればとおもいます。

※一年前くらいに行っていた開発なので今ならまた変わってくるかとおもいます。参考程度にご覧ください。

全体の構造

今回作成するのはWebアプリケーションで、なおかつ規模もそこまで大きなものでないため、単純な構成になりました。
それぞれのフレームワークや、技術選定に関しては当時共同で開発していた先輩がやってくれました。(ありがとうございます)

少しだけですが詳細について以下にまとめます。

フロントエンド

  • React (Create React App)
  • Redux saga
  • aspida
  • shallowrapper
  • scss

フレームワークはReactを採用しました。
特に大きな理由はないですが、しいて言うならTypeScriptと相性が良い点は強みでしたので、Reactになりました。
状態管理にはReduxを使用し、非同期での処理(APIへのリクエスト等)はsagaに任せていました。

結構あるあるな構成なんじゃないかなと思います。

テストはコンポーネント単位で作成していました。
基本的にテストが通らなければPRも出さないルールで運用を行い、コンポーネントを追加するときには一緒にテストも作成する流れで開発していました。

aspidaについて知らない人が多いと思うので簡単に説明すると、axiosやfetchなどのHTTPクライアントをaspidaでラップすることで、APIへのリクエスト、レスポンス等に型をつけることができるものです。

バックエンド

  • NestJS
  • TypeORM

バックエンドにはNestJSというフレームワークを使用しました。
こちらは去年のFIXERアドベントカレンダーの方で紹介しましたので、是非そちらもご覧ください。
https://tech-blog.cloud-config.jp/2019-12-17-introduction-for-nestjs/

その他諸々

  • firebase auth
    認証回り
    アプリケーションのアカウント管理
  • Github Actions
    CI/CDで使用
  • blob storage

よかったところ

TypeScriptの静的型付けがアツい。

現在大人気言語としてよく話題にあがりますが、TypeScriptはとても人気でしたので採用しました。
やはり、開発するうえで楽になる面が多いです。
バックエンドだと特にinterface等を使う場面が当たり前に存在しますし、型がある方が処理の流れを理解するうえで役立つことが多いです。

また、エディタによる補完機能を使って開発体験の向上も実感しました。

矢印キーとエンターだけでコーディングしよう!

既に若干そういう風潮がありますが、今後JavaScriptでできていた開発は基本的にTypeScriptが採用されることが多くなるのではないかと思います。

バックもフロントも同じ言語

一長一短かもしれませんが、同じ言語を理解していれば開発ができるので、バックエンドとフロントエンドで同じ言語を使っているのは大きいのではないかと思います。
実際express + Vueなどの設計はよく見聞きする印象があるので、世間的にもよくとられる手法なのかなと思います。

反省点・懸念等

TypeScript職人芸になりがち?

例えば以下のコードをご覧ください。

type Diff<T, U> = T extends U ? never : T;

type Options = {
    [K in "noImplicitAny" | "strictNullChecks" | "strictFunctionTypes"]?: boolean
};

type MappedDataDefinition<X> = {
    [key in keyof X]: number
}

これらは型の宣言なのですが、TypeScriptでは型のextendや、型を動的に変える機能(Generics)など、様々な機能があります。
これらはTypeScript独自のものであったり、ほかの言語でもあるものがたくさんありますが、なじみのない人にとっては初見でなにやっているかわからないところもあります。
かくいう私も正直TypeScriptを完全に理解していないので、おそらく3割くらいの機能しか使えていない状態でコードを記述していました。

インターネットではよくタイプ芸、型パズルなんて呼ばれているこのような型操作ですが、TypeScriptのコードの敷居をあげることになるうえ、型芸人がいなくなった後のメンテ性を考えると、一概に良いとは言えないかもしれません。
それはそれとして、TypeScriptの機能を使って簡単なバリデーションを作成するのは、実際パズルを説いているようで楽しいところもありますので、開発チーム全員でこの辺を学びながらTypeScriptの地力をあげるのが良いかと思います。

バックもフロントも同じ言語

よかったところで書きましたが一長一短なのかなと思います。
ちょっとくだらないかもしれませんが、複数のエディタでバックとフロントを同時に記述しているとどっちがどっちかわからなくなることがありました笑

冷静になれば大丈夫なのですが、開発が忙しい時などに頭が混乱するとわからなくなったりします。

テストが膨大

テストを書くのに不慣れだった側面が大きいですが、バックエンドとフロントエンドそれぞれで、エンドポイント毎、コントローラー毎、コンポーネント毎等、いろんな箇所でテストを記述していましたが、
後半になると管理するのが大変になってきた点があり、保守性と工数の兼ね合いがうまくいかなかった印象があります。
これはそもそもテストコードという文化がそういう側面を持っているので、むずかしい点だとおもいます。

練度あげます(自戒)

まとめ

弊社でやったなかで、始めてバックエンドからフロントエンド、インフラまで全体的にかかわった開発でしたので、知見という意味でも大きな経験になりました。
今後も開発していくエンジニアであるためにも、自分のなかで次につなげたいと思い今回ブログという形で記録しました。

明日はJunji Yamashita くんの「Kustoクエリについて」です。
是非ご覧ください。

それではまたどこかで。