1
/
5

マナリンクのフロントエンド開発環境【Nuxt×TypeScriptおすすめライブラリ編】

CTOの名人です。

今回はNuxt×TypeScript周辺に絞って、おすすめライブラリを並べていきます。TypeScriptを駆使してオンライン教育を革新していくメンバーを募集していますので、気になった方は応募してください!

composition-api系

Vue3から追加されたcomposition-apiは、個人的にはゲームチェンジャーになると言っていいほど革新的なものだと思っています(もちろんReact Hooksも)。

こんな記事も書いています。

vue-composition-apiで作るカスタムHook入門〜useHoge()を自作してみよう〜
vue/composition-apiの登場によって, Vue.js でも React の Custom Hook のような関数を簡単に作成できるようになりました. 本記事では, vue/composition-apiで作る API 呼び出し用の Hook として「useApi」を紹介しながら, 作成のコツや考え方を説明していきます. また, 最後には useApi 単体でのテストコードも添付しています. Hook のテストコードが気になる方もぜひ読んでください. vue/composition-apiの
https://zenn.dev/meijin/articles/34b9482dbc856d2523ed

簡単に言えば状態管理ごと処理を特定の関数に切り出すという設計思想です。非同期通信を多用するフロントエンドにおいては、非同期処理を行っている間、ローディングを出したり、エラーが返ってきたらエラー文言を出すと言った非同期処理と関連する状態の管理が煩雑になりがちです。そもそも非同期通信を実行する関数自体が、[通信結果のデータ、通信状態、エラー、その他状態]をセットで返してくれたら、関数の呼び出し側はそれらをViewにバインドするだけで済むやん!という発想が優れていると思っています。

@nuxtjs/composition-api

https://github.com/nuxt-community/composition-api

Nuxt.jsでcomposition-apiを繋ぎこむためのプラグインです。

defineComponentやsetupといったcomposition-apiの機能が使えるのはもちろん、useContextというフックでContextオブジェクトを取れるといったNuxt独自の機能も備えており便利です。公式のプラグインということもあり、Nuxt3になったときもそこまで酷いデグレはしないんじゃないかなと期待しています。

const context = useContext() // context.app.$pluginNameが使える

2021年2月下旬時点では、依存している@vue/composition-apiは1.0.0-rc系なので、そろそろ安定しつつあるのではないかと思います。

"@vue/composition-api": "1.0.0-rc.1",

vueuse

続いては、Vueuseというライブラリです。その名の通り、Vueを使ったuseHoge()のカスタムフックを集めています。

https://github.com/vueuse/vueuse

VueUse
Collection of essential Vue Composition Utilities
https://vueuse.org/functions.html

ちょっとなんでもかんでもuseHoge()にしたらいいってもんじゃないよってくらい色々なフックが集まっているのですが、以下の関数は便利かなと思います。

https://vueuse.org/core/useMouse/

useMouseはマウスの位置を返すフックです。

https://vueuse.org/core/useWindowScroll/

スクロール位置を示すフックです。現実的には、現在どっち向きにスクロールしているかを取りたいときがあったので、以下のように内製でuseScrollを拡張したものを作りました。isUpとかisDownで向きがわかります。

import { useWindowScroll } from '@vueuse/core'
import {
  reactive,
  toRefs,
  watch,
} from '@nuxtjs/composition-api'

export const useScroll = () => {
  const { x, y } = process.browser ? useWindowScroll() : { ...toRefs(reactive({x: 0, y: 0})) }

  const state = reactive<{
    isUp: boolean,
    isDown: boolean
  }>({
    isUp: false,
    isDown: false,
  })

  watch(y, (newY, oldY) => {
    if (newY > oldY) {
      state.isUp = false
      state.isDown = true
      return
    }
    if (newY < oldY) {
      state.isUp = true
      state.isDown = false
    }
  })

  return {
    x,
    y,
    ...toRefs(state),
  }
}

SWRV

続いてはSWRVです。これはフロントでStale-while-revalidateしてくれるAPIクライアントライブラリです。弊社のマナリンクではほとんど使うべき場面が見つかっていないので、軽い紹介まで。

Kong/swrv
swrv (pronounced "swerve") is a library using the@vue/composition-api for remote data fetching. It is largely a port of swr. The name "SWR" is derived from stale-while-revalidate, a cache invalidation strategy popularized by HTTP RFC 5861. SWR first retur
https://github.com/Kong/swrv

Stale-while-revalidateが肝とはいえ、単にAPI通信を実行して、errorやisValidatingといったステートを一緒に返してくれるという点だけでも利用価値はありそうです。Stale-while-revalidate自体も、本質的には呼び出し側がStale-while-revalidateやってるな〜って理解しながら呼び出すのは不便なので、脳死でStale-while-revalidateさせるように考えて組めばいいのかもしれません。

const { data, error, isValidating, mutate } = useSWRV(key, fetcher, options)


開発補助系

schema-dts(SEO対策系)

https://github.com/google/schema-dts

SEO対策でよく行われる構造化マークアップを型安全にするライブラリです。Googleがメンテナンスしており、退屈になりがちなSEO対策のDXを向上させてくれます。

JSON-LDを生成する以下のライブラリも便利です。

https://github.com/ymmooot/nuxt-jsonld

個人的には、型安全なパンくずリストについての研究を進めたいと思っていて、固まったらnuxt-typesafe-breadcrumbsといった命名でnpm公開しようかなと思っています。

Nuxt×TypeScriptで型安全にディレクトリ構造を統一したパンくずリストを実装する - Qiita
Web開発において、パンくずリストを正しく設定することは、ディレクトリ構造を検索エンジンに伝える上で重要です。 しかし、サイト内の多種多様なページでそれぞれパンくずリストを実装していると管理が煩雑になり、ディレクトリ構造が矛盾してしまうリスクが起こります。 ...
https://qiita.com/mejileben/items/411910c332953907b1e5


ts-auto-mock

Typescript-TDD/ts-auto-mock
Need help? Join us on Slack A TypeScript transformer that will allow you to create mocks for any types (interfaces, classes, etc.) without the need to create manual fakes/mocks. Quick overview Find the changelog here: Changelog. You can find the roadmap o
https://github.com/Typescript-TDD/ts-auto-mock

これ結構すごいです。

型定義から、モックデータを自動生成するファクトリのようなライブラリです。

import { createMock } from 'ts-auto-mock';

interface Person {
  id: string;
  getName(): string;
  details: {
      phone: number
  }
}
const mock = createMock<Person>();
mock.id // ""
mock.getName() // ""
mock.details // "{ phone: 0 }"

テストコードを書くときにとても便利です。大きめの型でも簡単にダミーデータを用意できます。


aspida

aspida/aspida
TypeScript friendly HTTP client wrapper for the browser and node.js. Path, URL query, header, body, and response can all specify the type FormData / URLSearchParams content can also specify the type HTTP client supports axios / fetch / node-fetch Reproduc
https://github.com/aspida/aspida

何百回と言っていますが、TypeScriptでREST APIを叩くならaspidaというライブラリがおすすめなのでぜひ使ってください。これがあるので1年半前の自分がTS対応に踏み切れました。


最近注目のライブラリ

VeeValidate

useField
useField is a custom composition API function that allows you to create data models that's automatically validated that you can then use to build your own custom input components with validation capabilities. It is very useful if you plan to build a UI co
https://vee-validate.logaretm.com/v4/api/use-field

フォームのライブラリですが、最新のV4ではVue3の記法を採用しており、勝手に注目しています。現在僕はVuelidateを使っていますが、NuxtのVue3対応を待って、こちらのVeeValidateに移行しようと思っています。

useFieldといったフックがあることで、ロジックとUIを切り離せるのが嬉しいです。Vuetifyとかは、UIとロジックが密結合しちゃうので、ロックイン度合いが高すぎるように思っています。


ts-auto-guard

rhys-vdw/ts-auto-guard
Generate type guard functions from TypeScript interfaces A tool for automatically generating TypeScript type guards for interfaces in your code base. This tool aims to allow developers to verify data from untyped sources to ensure it conforms to TypeScrip
https://github.com/rhys-vdw/ts-auto-guard

まだ常用していないのですが、Type guardを自動生成するCLIツールで、結構便利そうです。なにかとタイプガード使いますからね。


そもそもどうしてNuxt×TypeScriptをやっているのか

ちょっとだけ技術選定的な話もしたいなと思います。

まず、スタートアップではMPAでガツンとモノリシックで構成する企業も多いと思いますが、なぜSPAを採用したのか、です。

オンライン指導をマナリンク上で完結させるWebアプリケーションおよびスマホアプリを開発していくにあたっては、中長期的にはリッチなSPAをベースに先生向け、ご家庭向けの管理画面を構築していきます。

現時点ですでに、Web上でリアルタイムチャットができる機能を構築しています。

シンプルなチャットとはいえ、テキスト、画像、ファイル送信に対応し、また先生がご家庭ごとにメモを残せたり、生徒の学年や志望校を見ながらチャットできるようなUIを開発しています。もちろん決済機能もあるため、先生が日々の売上を管理する機能なども備えています。

今後、指導日を管理できるカレンダー機能や宿題や学習状況をすり合わせしていくようなUIを作っていく予定です。要は、かなり次々に画面上で操作していくUIになると見込んでいます。これらの画面をMPAで作ると、なにか操作するたびに都度リロードを挟まないといけなかったりします。致命的ではないにせよちょっともっさりしそうです。

また、実装工数においても、jQueryでリアルタイムチャットを構成するとなると、現在においては明らかにSPAのほうが楽だと感じていますし、JSのエコシステムがSPAを興隆させる方向に向いているので、リッチなUIを作り込んでいくのであればSPAのほうが望ましいと思います。

マナリンクもはるか昔はLaravelのMPAでしたが、こうなっていくことがなんとなく見えていたので、1年半ほど掛けて、フロントを全部Nuxtにリプレイスした経験があります。今のところ、その判断自体は間違っていなかったと思っています。

SPAのなかでも、NuxtとNextが2大勢力的な感じですが、当時の自分がVueしか触れなかったのでNuxtを選定したのが正直なところです。ただ、今の僕の実力を持ってマナリンクをスクラップアンドビルドするのであれば、もしかするとNext.jsを選ぶかもしれません。Reactを使ったほうが、マナリンクのアプリがReact Native製のため相性がより良いからです。加えて、ISRを使うとSEOが重要な一覧系のページでも表示パフォーマンスを出すことができ、UXとパフォーマンスの両立が図れます(※2年ほど前のNext.jsは今ほど成熟していなかったと思うので、当時にタイムスリップした、という想定にするとNuxtかも)

Next.js × TSX に Zero-runtime CSS in JS の linaria を導入する
Next.js9.5 系に linaria を導入する方法を解説します。 個人的に結構有名な組み合わせかと思っていましたがググっても見つからず、少し苦労したので記事にしておきます。 Next.js については React の Web アプリケーション向けフレームワークということで知名度が高いと思いますが、 linaria についてはまだ知名度が比較的低いかもしれません。 特筆すべき特徴として、 Write CSS in JS, but with zero runtime, CSS is extracted
https://zenn.dev/meijin/articles/a8163992c8e845fb382f


また、TypeScriptをやっている理由ですが、もはや素のJSで書くのは安全ではないと言い切れるからです。加えてTypeScriptはエコシステムの巻き込み方がうまく、既存のJSライブラリにあとから型をつけることができる点などが優秀です。Conditioinal Typesなどを使い込んでいくと、型定義のレベルでそれなりのプログラミングができるくらい型の表現力が豊かで、多種多様なデータを扱うフロントエンドに相性がいいです。僕はPHPやRuby出身のWebエンジニアですが、LL言語中心で育ってきたエンジニアにジェネリクス等を含めた型の概念を教育するという意味でも素晴らしい功績を果たしている気がしますw

よく言われるVueとTSの相性ですが、Reactなどと比べてしまうともちろん良くないです。しかし、批判するほど悪くないと思います。それは、ReactよりHTMLやCSSに対してフレンドリーなVueの思想があるからある意味当然なことです。技術を批判するときはトレードオフを考慮しないといけないな、とよく思います。あえていうと、composition-apiのRefやReactiveの使いどころの違いとか、JS内ではいちいち.valueを付けないといけないといったあたりが、React Hooksと比べるとちょっと書きにくいな、とは思います。


[ポエム]VueとReactとCSSについて思うこと2021/1月版
Moduleによるエコシステム構築が神のシステムだと思う。 これはNext.jsに類似の仕組みがない。Moduleは神。 これ以外の仕組みは割とVueの色々なライブラリに従っているだけだと思っている。Moduleが素晴らしい。 個人的にはNuxtにはIncremental Static ...
https://zenn.dev/meijin/scraps/fc5bcd737dc397


今回は以上となります。

TypeScriptを駆使してオンライン教育を革新していくメンバーを募集していますので、気になった方はぜひぜひ応募してください!

株式会社NoSchoolでは一緒に働く仲間を募集しています
3 いいね!
3 いいね!
同じタグの記事
今週のランキング