#えむけーろぐ

テキトーなことしか書いてません

Cursor-basedなページネーションをやめてpage-basedなページネーションに

先日作り直したPodcastのWebサイト。

blog.m6a.jp

GraphQL APIのepisodes一覧のfield(言い回しが正しいのか自信なし)を、Cursor-basedなページネーションで実装してしまったせいでPrev / Nextなページネーションしか出来ず使いにくくなっていた。

f:id:mktakuyax:20210506133429g:plain

Cursor-basedなページネーションで使いにくい様子(前・次の移動しかできない)

これを、Page-based(前のブログではOffset-basedと言っていたが、同じ意味)に作り変えた。

こんな感じ。

f:id:mktakuyax:20210516231829g:plain

Page-basedなページネーションができるようになった。(前・次だけでなく、ページ番号指定で移動できる)

これで少しは使いやすくなったはず。……なのだけど、本番のデータでやってみると、横幅がオーバーしてしまっていたり、スマホだともう崩壊していたり。

f:id:mktakuyax:20210516232136p:plain

f:id:mktakuyax:20210516232238p:plain

開発環境だけでなく、本番同様のデータでテストする重要性を噛み締めた出来事であった。

 

ちなみにgraphql-rubyでいい感じにpage-basedなページネーションをやるのに、graphql-paginationというgemがあったのでそれを使った。メンテされているかどうか判断するのに微妙なラインだったけど、最悪自分で実装できそうだったので一旦採用してみることにした。

github.com

PodcastのWebサイトをNext.js + GraphQL APIで作り直す

はじめに

Next.jsやGraphQLを学ぶ機運の高まりがあったので、GWの期間を使ってゆるふわPodcastのWebサイトを作り直してみた。Rails on HerokuなMPA(SPAの対義語としてMulti Pages Applicationと言うらしい)から、Next.jsによるSPA + GraphQL APIという感じ。

yuru28.com

f:id:mktakuyax:20210506130659p:plain

yuru28.com

ユーザに見える部分( yuru28.com )をNext.js on Vercelで構築し、従来のRailsアプリにはapi.yuru28.comとしてGraphQL APIと管理画面をやってもらうことにした。

フロントエンド(Next.js, Apollo Client, Chakra UI)

`npx create-next-app yuru28-com` してガシガシ作っていくだけ。デフォルトだとただのJSなので、TypeScript対応*1もしておいた。ページごとにSG(静的HTML生成)、SSR(サーバサイドレンダリング)、そしてCSR(クライアントサイドレンダリング、普通のSPA的な)を選択したり組み合わせたりすることができる。今回の要件だとTOPページ以外はSGで構築することが出来た。

後述するGraphQL APIを叩くために、Apollo ClientというGraphQLのライブラリを使用している。Next.jsとApollo Clientを組み合わせる方法は、Apollo公式のブログにわりと丁寧に書いてあった。SG、SSR、CSRそれぞれの場合のApollo Clientの使い方が書いてあるので読んでおくと良さそう。
Getting Started With Apollo Client in Next.js - Apollo Blog

UIフレームワークとしては、プロフィールサイトを作り直したとき*2に素振りしたChakra UIを採用した。Bootstrapを使っても良かったが、今だとChakra UIの方が流行りらしいということでこっちにした。ネイティブでTypeScript対応していたりするおかげで、コーディング時の体験はなかなか良かった印象。Bootstrapのようにクラスを当てていくのではなく、ReactらしくComponentをimportして使っていくので、そのへんがちょっとめんどくさかった。基本的には、公式のドキュメントをざっと見てどういうComponentがあるのかを頭に入れておいて、作りながら良さそうなComponentを使っていくというスタイルで開発を進めた。

GraphQL API

GraphQL APIは、既存のRails製Webサイトに生やした。RailsでGraphQLといえば、graphql-rubyを使うのが定番らしい。公式のドキュメントを流し読みした後、良さげな入門Qiita記事*3があったのでそれにそって基本のAPIを構築してみた。

ひたすらTypeを定義して、fieldを追加し、必要に応じてresolverを書くという作業ゲー。管理画面もNext.jsで作るとなるとMutationとか必要になるけど、一旦はユーザに見えるページだけをNext.js化して管理画面はそのままなので、今回はQuery書くだけだった。ある程度API側が出来た段階で api.yuru28.com にデプロイし、既存の管理画面以外のページを削除した。

何故かGraphQLのAPIのpaginationはCursor-basedでやるものだという先入観があったので、そういう感じでエピソード一覧のAPIを実装してしまったのだけど、普通にOffset-basedでやればよかったなという後悔がある。Cursor-basedでpaginationをやってしまうと、以下のGIF画像のように、常に prev or next のページ遷移しか出来ずに不便。週イチでしか増えないエピソードというデータに対して、cursor-basedなpaginationは明らかに向かない。あとでOffset-basedな感じに作り直そうと思う。

f:id:mktakuyax:20210506133429g:plain

Cursor-basedでページネーションを実装してしまったので不便な様子

 

デプロイ

フロントエンドのコードは、Vercelにデプロイしている。特に特別なことはしていないが、GitHub経由でログイン後にリポジトリを指定し独自ドメインまわりの設定をするだけで動いてくれて便利。

サーバサイドのコードは引き続きHerokuで動かしている。

おわりに

GW後半の3日間でサクッと実装することが出来た。ひとまずPodcastのユーザ側に見える部分だけNext.js化したので認証は無いのだが、管理画面もNext.js化してそのあたりの知見を溜めておきたい。Auth0でも使いたいなぁ。

Next.js、Apollo Client、Chakra UI、GraphQLと、新しい技術が盛り沢山だったが楽しくものを作ることが出来た。今後もサイトの改善をしつつ、働き始めてからあんまり出来ていなかった雑なWebアプリ量産なんかもこの技術スタックでやっていきたいなと思っている。

コアラマットレスとコアラピロー

二人暮らしをはじめて約1ヶ月。同居人が来る前に、ソファとテーブル、そしてテレビを揃えたのだけど、寝床についてはシングルベッドに無理やり二人で寝るという感じだった。どう考えてもリビングまわりよりもベッドの方が優先順位高いだろと思うのだけど、きっと頭の中から抜け落ちてしまっていたのだろう。

案の定睡眠の質は下がり、日々つらい思いをしていたのだが、一念発起してダブルのベッドとマットレスを購入することにした。

そんな中、YouTube依存症の同居人がはじめしゃちょーの動画で見たコアラマットレスがほしいと言い出した。名前だけは知っていたがまさか自分が買うとは思ってなかったので、価格を調べてみるとなんとダブルで92000円。みんな大好きニトリで適当なポケットコイルマットレスでも買おうかと思っていたので僕にとってこの価格は高すぎた。ベッドとマットレス、布団やシーツなど諸々含めて10万円という予算で脳内稟議を通したのに、マットレスだけで約10万円というのはキツい。というわけで最初は反対したのだけど、まぁ強い要望やらなんやらがあって最終的には購入した。

jp.koala.com

で、1週間寝てみたのだけど、これがまたなかなか良い。あまりその辺りに対する意識というか、モノを見る目があまりないので詳細なレビューは出来ないのだけど、なんとなく体が浮いているような心地よさを感じることが出来ている。寝起きのだるい感じも特にない。ただ、ニトリのシングルマットレスからコアラマットレスのダブルに移行したので、今回手に入れた良好な睡眠体験が、シングル→ダブルによってもたらされたものなのか、ニトリ→コアラによってもたらされたものなのか、あるいはその両方なのか確実なことが言えない。その辺りの価値検証をちゃんとやるなら、A/Bテストをするべきだが、そうするためにはニトリのダブルマットレスとコアラのシングルマットレスとコアラのダブルマットレス、そしてそれらに対応した寝具各種をそれぞれ購入する必要があり、合計費用が20万円以上かかってしまう上、良質な睡眠というKGIに対して何をKPIとすべきかがよくわかっていないので、その辺りの検証は割愛させてもらうことにした。

 

さて良いマットレスを手に入れてしまうと、良い枕もほしくなってきた。そもそも自分は枕を使わないタイプの人間で、タオルケットを適当にまるめて枕代わりにしていたのだが、いい感じに体が沈み込むようになった今、タオルケットで寝ることに違和感を覚えるようになってしまった。なんとコアラのシリーズに枕もあるらしいということで、一瞬迷った末にコアラピローも購入した。

jp.koala.com

枕に12000円も払うのは正直言って異常だと思ったが、そもそもマットレスに10万払ったあとなので金銭感覚が麻痺しており、迷いなく購入まで進むことが出来た。結果これもかなり良い感じで、頭を含めた全身が浮いているような気持ちで睡眠をすることが出来ている。また、中には低反発のジェルが入っているらしく、ひんやり系の質感が好きな僕にはぴったりだった。

 

そんなわけで、最初は購入に反対していたコアラマットレスだが、見事虜になり最終的には枕まで購入してしまった。これはよくあるパターンで、最初はペットを買うのに反対していた父親が実は一番散歩や餌やりを熱心にやっているみたいな話である。

この記事を読んで自分もそのマットレスを試してみようと思った人は、下記リンクから購入ページに遷移すると1万円引きでマットレスを購入することができる。僕も3000円引きでコアラ製品を買えるようになる。いわゆるWin-Winなので、買おうと思っている人は頭の片隅に入れておくべし。

http://frndby.co/v/takuyamk96

Next.jsを使ってプロフィールサイトを作り直す

長らくGitHub Pages + Jekyllで運用してきた我がプロフィールサイトのm6a.jpだが、Next.jsを学ぶ機運が高まったので作り直すことにした。

f:id:mktakuyax:20210504112934p:plain

https://m6a.jp

ちなみに、ドメイン名のm6aはmktakuyaもしくはmukohiraのnumeronym*1である。internationalizationがi18nになったり、kubernetesがk8sになったりするやつね。ハンドルネームも苗字も8文字だからどっちもいけて便利。

やってることは大したことなくて、Next.jsでサイトを作ってVercelにデプロイしているだけだ。Next.jsはVercelが作っているReactのフレームワーク。Vercelはそういう名前の会社で、同名のホスティングサービスもやっている。

UIフレームワークとしてはChakra UIを使っている。React向けのフレームワークで、Railsのviewで使ってたBootstrapのような軽い気持ちで使える気がする。

せっかくNext.jsを使っているのだからということで、Blog記事一覧の部分はStatic Generation機能を使ってビルド時に生成している。このブログのRSSフィードを読み込み、最新5件の記事情報をリストで表示している。

このブログ記事一覧はStatic Generationしている単なる静的なコンテンツだから、記事が更新されたタイミングで再度ビルドを走らせなければならない。VercelにはDeploy Hooks*2という仕組みがあって、事前に生成した特定のURLに空のPOSTリクエストを投げるとそれを起点にして特定のブランチをデプロイしてくれる。今回は、IFTTTを利用してフィードの更新を検知し、Webhooks機能を使ってビルドを走らせることにした。

f:id:mktakuyax:20210504112408p:plain

VercelのDeploy Hooks

f:id:mktakuyax:20210504112350p:plain

IFTTTの設定

今の所単なるペライチでしかないのだが、今後は作ったもの一覧なんかを載せていきたいと思っている。仕事で使う技術を使うという意味では、Railsで作ったものを管理する管理画面とAPIだけ作ってまたNext.jsのSGを使うでもいいし、今風のものを使うならmicroCMSのようなヘッドレスCMSを使うでも良い。

フロントエンド界隈は流れが早い上にいろいろなものが細々としていたり、他人の言葉を借りると技術的断絶が起きまくっている*3という印象で正直近寄りたくなかったのだけど、Next.jsが良い感じに秩序をもたらしてくれているっぽくて、これなら楽しんでモノを作れるなーという気持ちになっている。

動画による学び

ビジネスを学べるオンライン動画サービスを作っていた*1身でこんなこと言うのもなんだけど、正直言って動画による学びというものに可能性を感じていなかった。動画のペースに自分が合わせるより、自分のペースで文章を読んだほうが早いじゃん、みたいな。

ところがここ最近新しいことを学ぶのに動画を利用している自分がいる。前の職場や今の職場で自分でインフラを触る必要があったりした時に、かなり知識不足を感じていたのでAWSを学びたいとなったとき、ハンズオン形式のものでも試してみるかということでUdemyの動画を購入してみた。

www.udemy.com

また、最近GraphQLをやる必要が出てきてしまったので、さっと概要をさらうために以下の動画をやってみたりなどした。

www.udemy.com

今は、また別件で用事のあるGoogleアナリティクスの動画なんかを視聴しているところだ。

 

何本か動画による学びをやってみて、以下のようなポイントを掴めた気がする。

  • 1.5倍〜2倍速で再生する
  • 手動かす系の動画は、2枚以上のディスプレイがある環境で視聴する
  • 1本あたり長くても20分程度(倍速再生だと10分!)なことが多いので、出来るだけ動画の途中で中断しないようにする

1個目。これは今どきのワカモノ*2の間では常識らしいけど、動画は等倍速で見るものではないらしい。実際、等倍速で聞いていると自分で文章読んだほうが早いじゃんと思ってしまう。それなら、自分のペースに動画を合わせれば良いのだ。なんとなく、コンテンツ自体も倍速再生を前提で作られているんじゃないかという気がしている。

2個目。これは1枚目のディスプレイにエディタなり作業用ブラウザなりを、2個目のディスプレイに動画を配置するためだ。ハンズオン形式の動画で、画面半分に動画を配置するという場合、意外と動画内のエディタの字が小さくて困るということがあるので、ディスプレイいっぱいに動画を表示でき、かつ別で作業も広い画面で出来る環境で学習をしたほうが良いだろう。

最後。仕事や家事の合間に勉強をする必要のある状態だと、キリのいいところまでやるというのがなかなか難しかったりするが、少なくともUdemyの動画に関しては1本あたりの長さがそれなりの長さで収まっていたりするので、頑張って動画の終わりまでは終わらせてから席を外したほうが良いだろう。ブラウザを閉じたりした後に途中から再生しようとすると、前回の箇所を覚えてくれていなかったりするので、そういう意味でもキリの良いところまでやったほうが良さそうだ。

 

そんなわけで、たぶんめちゃくちゃ今更だと思うけど、動画による学びって結構アリなんだなーと思ったという話でした。

NETGEARのメッシュWi-Fiルーター Orbi RBK50

NETGEARのOrbi RBK50というメッシュWi-Fiルーターを導入した。

もともとはNTTから借りているHGW(ホームゲートウェイ)の無線LAN機能を利用していたが、どうも調子が悪く、ゲーム中に突然2〜3分使えなくなってしまう。*1 仕事用PCなど確実に切れてほしくないものは有線接続していたので無問題だったが、同居人がリモートワークするときにはWi-Fiを使用していたり、先日ゲーム中に接続断になってしまったりなどの事情があり、別途Wi-Fiアクセスポイントとなる機器を購入しようと思っていた。

またPodcastの収録用に自室のウォークインクローゼットを使いたいという計画があるのだが、ホームゲートウェイのあるリビングから電子レンジや冷蔵庫等ノイズ源のあるキッチンを挟み一番奥まった場所にある自室の更に奥まった場所のウォークインクローゼットで、それなりに回線品質が求められるPodcastの収録を行うのは現状のセットアップだと無理ゲーだなぁという事情もあった。

当初は適当な市販のWi-Fiルーターを2台購入し、アクセスポイントモード + 同一SSIDでローミング運用をしようと思っていたのだが、そこまでお金かけるならもう少し出して流行りのメッシュWi-Fiシステムでも導入しようと思いたったのであった。

メッシュWi-Fiシステムにおいて、親機とサテライト間の通信はバックホールというらしい。新居は全部屋にLANポートがあるので、ルーターとサテライト間の接続は有線で行いたく、事前にそれが可能なことを確認した。

 

結果、かなり良い感じだ。

f:id:mktakuyax:20210428133440j:plain

Orbi RBK50の親機。想像の2倍くらいデカい

我が家の構成だと、何も考えずに挿すと二重ルーター状態になってしまうので、Orbiをアクセスポイントモードにするか、HGWをただのONUとして使いルーター機能をOFFにするかの対処をする必要があった。試してみたところ、後者だと何やら接続速度が遅くなってしまったり、IPv6が無効になってしまったりといった問題が発生したので、前者で対応することにした。

管理ツールもおしゃれで、以下のようなWebの管理画面や管理用iOSアプリなどが提供されている。

f:id:mktakuyax:20210428134349p:plain

f:id:mktakuyax:20210428134416p:plain

導入前はトイレや玄関、自室では弱かったWi-Fiの電波も、家中どこでも3本立っている。これでより良いインターネット生活ができそうだ。

*1:DFSの対象となるようなチャンネルではなかったはず。

開発者にとって良いパートナーとは

社内Slackでいろいろアウトプットしてたり、Podcastで喋り倒してしまって満足して、あまりブログを書かなくなってしまったが、久々にぼんやりと考えることがあったので記事を書いておきたい。

最近はBizサイド出身のPdMと一緒にお仕事させてもらっている。その方の(たぶん)上司にあたるPdMはエンジニア出身で、ある程度我々開発チームの言うことをエスパーしてくれている気がするのだけど、彼はそういうわけにもいかないので共通の言語を使って話す必要がある。これがなかなか難しく、そして楽しい。我々的にこれは無茶だろう、というようなこともなぜ無茶なのかを誠実に説明し、かつ技術面・工数面で現実的な代替案を提案し一緒に考え、なるたけ良い判断をしていただくための材料を提供する。このあたりのコミュニケーションスキルについては前職でかなり鍛えられたので得意だな、向いてるなと思う。一方で、toCでかつサーバからクライアントまで一人で担当しエイヤと出来た前職に比べ、toBでチケット切ってチームで分業して共有してとやらなきゃいけない今の職場は、これまでエイヤで済ませていた部分も言語化しなければならず、そのあたりのスキルの低さを日々感じている。

さてここ1ヶ月半くらいは、その彼と一緒に中規模の開発案件を進めており、僕は開発側のリードとして仕様策定からタスク分割、プロジェクト管理そしてもちろん実装などの面で伴走させてもらった。案件の性質上、開発チームでガッと機能作ってリリースではなく、機能開発と並行してBizサイドの皆様にデータ入力用のスプレッドシート(数千行クラス)を埋めてもらい、そのシートをCSVに落として本番DBにデータを流し込むという工程も必要だった。

もちろん機能開発やリリース周知のスケジュールを引くのと共に、このスケジュールでやるならいつまでにシートを埋めてもらわないとね、という話はしていたのだけど、開発チームの見立てとしては「まぁこういうのはだいたい締め切りまでに埋めてくれないよね」で、正直僕もそういう認識でいた。だいたいのBizサイドの方達は日常業務で忙殺されており、こういった片手間でやる系のタスクは後回しにされがちなのだ。(うちの会社がどうこう、ではなく一般論として)

でどうだったかと言うと、予想に反して(というと失礼な話だが)無事締め切りまでにすべてのデータが揃ったのである。もともとPdMが各チームの朝会を巡回して周知をして頂いたり、シートの埋まり具合を見ながらSlackで催促して頂く、という約束にはなっていて、こちらとしては開発業務に集中できてありがたいなぁと思っていたのだが、なんと締め切り直前には担当者に電話してお願いをしていたというのだ。Slack callやらではなく、090とか080とかの電話で、である。曰く、Bizサイドの人は結構電話でお願いするほうが動いてくれる、らしい。

これにはかなり驚いてしまった。「僕が同じ立場だったらそういう手段取れるだろうか?」と思った。思いつきすらしなかっただろう。おそらく、エンジニア出身の人でそういう手段を取れる人はかなり少数派だろうと思う。もちろんとても泥臭いやり方だし、そういうことさせないようなフローをこちらから提案できればもっと良かったのだが、一方でその手段を手札として持っていて、必要となればすぐに行使することが出来る、そんな人がプロダクト開発の現場に来てくれたというのは、とてもポジティブなことだと思う。

開発者にとって良いパートナーとは、というのをぼんやりと考えるのだけど、そのひとつの答えが掴めたようなそんな気がした出来事だった。

PdMにとって良いパートナーとは、どんな開発者だろうか?