苦しんで覚えるフロント設計 of Nuxt

みなさま、こんばんみ。ブロックチェーン事業部の城市と申します。
フロントエンドエンジニア(多分)として、主にNuxt.js/TypeScriptを用いて開発を行っています。

【前回の反省】では初めてのNuxtと起こったことについて書きました。その反省でAtomicDesign/TypeScript/ElasticSearchを導入しました。テストを書きました。それでどうなったのか。何が変わったのか。今回はそんな話をしていきます。

使ってる技術

  • Nuxtjs + TypeScript
  • Pug
  • AtomicDegisn
  • Firebase(Authentication/Functions/Firestore/RealtimeDatabase/Hosting/Storage)
  • ElasticSearch
  • Jest

状況

良かったこと

Pug

ずっと導入してるんですがそういえば触れてなかった。個人的にはあってもなくても、という印象。VueはそもそもComponentベースなのでメリットを享受しづらい部分はありますが、とはいえ書く量が減るというメリットはあります。反面、そんなに普及しているわけでもない(と思われる)Pugの書き方に慣れて変な癖が付く可能性があるので、HTMLで書いちゃうほうがいい気もします。結局は好みの問題ではありそう。

TypeScript

偉大。ある程度のルールができて、オレオレオブジェクトの削減や各vueファイル内での書き方の統一等たくさんのメリットを享受しました。型を切りきれていなかったりもっときれいに書けるようなところもありそうなので今後も要改善。沼は深い。困ったらObjectとかanyにするのをやめましょう。

ElasticSearch

複数のfirestore CollectionをCloud functions(onCreate/onUpdateトリガー)で集約して検索に利用。設計がいまいちだったのもあってバカほど負荷上がりしましたが何度かのスペックアップでなんとかしました。力こそパワー。更新頻度が高いCollectionはindex更新が愉快なことになるけどどう設計するのが正しいんだろう

AtomicDesign

Component設計の失敗とは書いたものの、これ自体は最低限の大方針になって無秩序に乱立しなかったので導入してよかったです。特にAtoms/Moleculesは(一部微妙なのもできましたが)まあまあの汎用性があり、Component設計としてはそれなりに成功といえます。Organismsが鬼門(n回目

今回の反省

Component設計の失敗

一つのComponentに役割を押し込みすぎ問題。AtomicDesignや!!と初めは綺麗に作ったComponentたちですが、何度も機能追加し手が入った結果AromicDesignによる分類が迷走、名前を見ても何のComponentなのかどこでどう使っているのかわからん上、中を見ても色々やりすぎて何だこれ状態になりました。大量のPropsで値を受け取りv-ifで表示切り替えをするカオスComponentが爆誕してたりしました。改修のたびに良くわからないComponentが爆誕するので整理し直さないとやばい。

SCSSの失敗

Component設計が悪かったのが主な理由なんですが、ほぼ全グローバルになった。なんで? よくある話ですがあっちを直すとこっちが崩れるみたいな状況に。flocssを取り入れましたが、メンテナンス性に難があったり沼に落ちた感があります。とはいえ私は初期の全体設計に一部携わったくらいなのでほとんど触れられてないんですが。 CSSなんもわからん。でもAtomicDesignを導入してるのにそうなってる時点でComponent設計が(ry

firebaseつらい

各種制限にぶち当たる。FirestoreのCollectionとFunctionsが沼。Firestoreの1ドキュメント1回/sやTransaction上限500件とか、Functionsのタイムアウト540sとかデプロイが遅いとかconfigのgetで503が出るとか。とはいえ設計で解決できそうな部分もありそう。

クソ重い

上記のいろいろが積み重なった結果バカ遅いサイトになりました。そのうちなんとかしないと。

テスト

導入して最低限は書くようにしましたが網羅しきれていないというのが現状です。ライオンのスタンドに怒られてしまいます。これについては今後も要改善。Cloud functionsのテストについては結構仕事してくれています。

今後どう改善していくか

Component設計について
  • Componentの役割を明確化すること
    どんどん機能を押し込んでいってはいけません。個人的には「名前をつけられる」というのが良さそうです。名前で何をするComponentなのかわかるレベルにすること。似ているからと行って共通化しまくると微妙な違いをv-ifで泣きながら場合分けすることになります。気をつけよう。そうすればCSSもScopedで定義できるのですっきりするはず。当たり前のことなんだけどだいたい迷子になった結果グローバルCSSになりがち(そうか?????)。
  • Organismsについて
    Atomsがら始めるのがAtomicDesign流らしいですが、そうして下から組み上げていくと出来上がったOrganismsの中には再利用しないものもあります。Organismsを利用するOrganismsも生まれます。なんもわからなくなりますね。これらに関しては、再利用するかどうかで考え再利用しないものはPagesに書く、で良さそうな気がします。Moleculesの集合ではないけど業務的に意味を持つのでOrganismsみたいなときもありますが再利用しないのであればPagesに書いてしまうほうがemit/propsのバケツリレーが短くなって良さそうです。ただし構造化はきちんとしておきましょう。将来的に分解しやすいです。
  • デザインはほぼ一緒だけど機能が違うComponentどうする?
    基本的にはそんな起こらないはずだけどまれに見るやつ。これが生まれた結果Component設計が失敗したみたいなところもある。Scopedでそれぞれにデザインを適応するのか、それともグローバルに持つのか。もしくは一緒のComponentにして気合で分けるのか。さてどうするのが正解でしょう。いまのところ、ComponentごとわけてそれぞれScopedでCSS書くのが良さそうな気がしてます。同じComponentにしてv-ifで分けるのはしんどいし、グローバルにしちゃうと統一性とか将来的に変わった場合にしんどい。
  • 処理をPagesに持つかOrganismsに持つか
    AtomicDesignの基本的な方針で言えば設計としてはPagesからpropsするのが正になります。しかし処理ごとOrganismsにもたせて共通化したほうが便利な場合も多々あるのでちゃんと考えましょうという話。とはいえ「Componentを共通化できる」=「デザインがほぼ共通+受け取るデータがほぼ共通」ということではあるので可能であれば基本的にはOrganisms側に持つほうがいい………と言いたいところなんですがそうすると今度は同じページのOrganismsAとOrganismsBで同じデータ取ってきてるじゃんみたいなのが発生します(結構起きてた)。下から組み上げると特に起こりやすいですね。というわけで、これは完全に場合によるのでどっちでやるかよく考えましょう
速度面

Firestore CollectionとElasticSearchの設計はかなり速度に影響するので要改善。あたりまえだけど取得カラム絞るとか。あとNuxtの問題なのか、assetsに画像置くと遅いのでstaticに入れたほうが良いとか。SSRの設計なんかもちゃんと考えられてないのでどうにかしたい。最近だとSSRはheaderだけでいいんじゃないかとかいう話もあるし。

UX

現状あまり考えられているとは言えない状況です。どうにかしたい。まあ諸事情でどうにもならない部分もあるんですが。

テスト

書け☝( ◠‿◠ )☝

振り返ってみて

毎回書いている気がしますが、これが正解というものはなくて、PJ/チームに合わせて最適なやり方を模索していくしかなさそうです。Nuxt/Firebaseを初めて触って失敗して、AtomicDesign/TypeScriptを導入するも迷走して、といろいろなことを学んできました。苦しんで覚えるフロント設計ですね。

学んだ中で言えることは「疑問を持つことをやめない」「必ず振り返る」ということです。常にこれでいいのか?と考え続けること。終わったあとこの記事のように、なにをやったらどうなったのかという記録を残すことです。それをやっておけばゆっくりとかもしれませんが状況は改善していくでしょう。きっと。

PR

tecotec.co.jp