fabfuel/ecs-deployを使うときに必要なIAM権限
やりたいこと
- GitHub Actions上でECRにDocker imageをデプロイ後、そのimageを利用するECSに空デプロイしたい
使ったもの
ちなみに調べると大体は下記を使う方法が出てくる。
が、今回の私の手元の構成だとtask definitionは別repositoryのterraformでpush, docker imageのもととなるアプリケーションはまた別repositoryという構成だったので使えない。
この構成がそもそもダメという説はある(当方、terraform初心者)。
ハマったこと
以下のエラーが出てデプロイができない
Unknown task definition arn: {task definitionの名前}
流れ、結論を超ざっくりいうと
- 原因はデプロイに利用していたIAMユーザの権限不足
- にも関わらずエラーはこれなので「コンソールだと存在するのに見つからないの…?」と混乱してた
- 実装コードを読みに行くとエラーを雑に丸めてtask not foundとしているだけになっていることを発見
- aws cliで直接実行して権限不足を確認
足りなかった権限
ecs:DescribeTaskDefinition
が足りなかった
エラーを握りつぶしてる部分
ここでcatchするClientErrorにはtaskが見つからない以外のエラー、今回なら権限不足のエラーも入ってくるが全部丸めてtaskが見つからないというメッセージが出力されてしまう。
ややこしいのは、この処理の前後では権限不足でもきちんとエラーを出してくれてるので対応できるのだがここにきてこれなので俺が悪いのか、となってしまった。
最終的に必要だった権限
{ "Version": "2012-10-17", "Statement": [ { "Sid":"DeployECS", "Effect":"Allow", "Action":[ "ecs:DescribeTasks", "ecs:DescribeServices", "ecs:DescribeTaskDefinition", "ecs:RegisterTaskDefinition", "ecs:DeregisterTaskDefinition", "ecs:UpdateService", "ecs:ListTasks", "iam:PassRole" ], "Resource": "*" } ] }
反省
AWS初心者というのもあったが、まだよくわからんものは横着して便利ツール使う前に泥臭く触るべきだったなぁという気持ちになりました。aws cliありがとう。
特に面白い記事でもないんですが同じことで死んでる人のために記事を残す。
該当のコードについては気が向いたらPR出そうと思います。
近況報告
僕のことを知らない人はどうでもいい記事なので回れ右してください。
目次
- 退職します
- 3年間本当にいい経験できたので振り返らせてくれ
- 今後
退職します
3年間ありがとうございました! pic.twitter.com/tAZFoS0xhW
— きりん / kirin (@sota1235) January 28, 2020
現職のメルカリを退職することにしました。
言語化するのが難しいので理由は詳しく書きません。1つだけ強く書いておくとネガティブな理由ドリブンではないし、この記事では基本的に自慢か会社を褒めるしかしないです。
理由をざっくり言語化するなら、入社前にこの会社でやりたかったことにそれなりに取り組めたこと。
それ以上に自分が想像していなかった体験をさせてもらえたこと。
それらを通じてまた別にやってみたいことができたことです。
働いている間の経験は本当に濃いもので3年間とは思えないものでした。雑に振り返る。
3年間の経験
USに行った
今でも覚えてる、入社1週間経ってからの流れ
- メンター「この会社、来週からUS行ってとか普通にあるからパスポート更新しておいてね」
- 私「あ、はい。(まぁ脅しでしょ)」
- (2週間後)
- メンター「再来週からUS一ヶ月ね」
- 私「ファッ!?!?」
まさか試用期間中の当時はジュニアと言われてもぐうの音も出ない私という人材を貴重なお金を使って出張させたりしないだろうとたかを括っていたので、大急ぎでパスポートを作った記憶があります。
行くぜ、パスポート紛失届
— きりん / kirin (@sota1235) January 24, 2017
行くぜ、パスポート発行
— きりん / kirin (@sota1235) January 23, 2017
英語もろくに聞き取れず、開発のスピード感についていくのに必死だった。とても、とても楽しかった。
思えばこの経験がきっかけで必死に英語を勉強し始めた気がする。
英語をそこそこ習得した
そこそこ、と称した文脈としては以下の通り。
- 英語しか喋れない同僚と仕事をすることができるようにはなった
- しかしながら多少生産性は落ちる
- 一方で学問的な観点ではほぼ成長していない、と捉えることもできる
「コミュニケーションの手段としての英語」だけを頑張ってきたので例えばTOEICの点数はおそらく入社当時から大きく変わっていないし覚えてる単語数にも大きな変化はない。
しかしながら会社で一緒に働く英語話者と仕事をしたり、海外カンファレンスで登壇者に聞きたいことを聞き出すだけの英語は身についた。つまりはSpeakingとListeningは身についたかなと思う。
これは多少言い訳ではあるのだが、社会人で英語に限らず何かを勉強するって相当難しい。
そもそも週5で労働していて週2日しかないうえに学習したことを反復して毎日活かせるわけでもないので学生の頃よりは圧倒的に勉強したことが身につかない。
私もUS出張直後は参考書を買って勉強しようと試みたが結局挫折してしまった。
それでもここまで英語が喋れるようになったのは、会社の補助でオンライン英会話をほぼ毎日、就業直後のまだ気力があるタイミングでオフィスで受けられたこと。そして実際にリアルの会話をする機会が社内に溢れていたことに限る。
もちろんそれだけだと英語力は頭打ちになるし、実際今はなっていると思う(余談だが、日本に住んでいる外国人の英語はめちゃくちゃ優しいと思う、日本人が英語が苦手なことを無意識に知っている)。
それでも自分がコミュニケーションを取りたい優秀な人に人の力を借りずに話せるのはこれから先もかなりアドバンテージだなと思う。
海外カンファレンス参加
入社当時から今も変わらない文化として、アウトプットしてるものにはインプットの機会を与える、というのがある*1。
そのため、というわけではないが自分の力を磨いたり常にベンチマークできるように内外問わずアウトプットをしてきたおかげか、国内外問わず様々なカンファレンスに会社の援助を受けて参加させてもらった。
以下は私が会社に参加させてもらえた海外カンファレンス達。
Firebase Dev Summit 2017の参加権を得て、初めて参加のチャンスが転がってきた時のことが印象的だったのをよく覚えてる。
私は性格上、自己評価も低いし何事も遠慮しがちなので当時のCTO(@sotarok)に顔色を伺うように「私なんかが行ってもいいんですかね…?」っといった感じで相談した。
そしたら「行ってもいいけど、行きたいの?」というような感じで私自身の意思みたいなのを確認されて、若手意識じゃないけど自分は未熟だから許可を取らなきゃいけないとか、100%のリターンが無いとお金のかかる行動を起こしてはいけないみたいな無意識の遠慮がスパンと消えた記憶がある。
それからはチャンスがあったら自分の頭でコストとリターンも考えつつ、一人の開発者としてどうしたいのか、行ったらどうなれる可能性があるのかとかも考えられるようになった。
CTOはもちろん、当時行って来いと背中を押してくれたチームメンバーの人にも心の底から感謝しています。
メルチャン立ち上げ
2017年の7月にメルカリチャンネルというサービスを立ち上げたのですが、初期の開発からその後、約1年ほど運用をしていました(※2019年7月にクローズ)。
一ヶ月近く死ぬ気で開発したのでぜひ見てフィードバックください!https://t.co/82YCCDyyCP
— きりん / kirin (@sota1235) July 6, 2017
当時の思い出は書き出すと本当に長くなるしまとまりもないので箇条書きで書くと
- 素早く、最低限の品質で出す開発を経験できた
- 全く触ったことのなかった技術スタックに触れることができた
- よかった副産物として、それを外部にアウトプットすることでいいつながりも増えた
- プロダクトのことを死ぬ気で考え抜いて開発の立場からできることを考える、という入社した際に目標にしていたことを肌で体験できた
私には「これが無いと生きていけない」というなにか(Webサービスじゃなくても何でもいい、なにか)を作るというのが人生の目標のうちの1つなんですが、メルチャンではそれを一定、叶えることができたと実感できたのがよかった。
実際に作ったものに対して利用してるお客様から生の反応がもらえ、ときには対面でフィードバックをもらうこともできました。
クローズまで面倒を見ていたわけではないものの、半永久的にお客様を幸せにし続けることができなかった、という点は未だに悔しさもあるので来世で頑張りたい。
採用へのコミット
一時期ではありますが、採用プロセスに参加させてもらってました。
それに関する自分のアウトプットは振り返ると本当に反省が多いのですが、それまでエンジニアリングやプロダクト作りにしかフォーカスしていなかったので、人にフォーカスしなければいけない採用は非常に刺激的な経験でした。
今振り返るとああできたらよかったのに、というタラレバだらけなので次の場所でもチャンスがあったら頑張りたい。
個人的な目標としては再現性のある採用がしたい…。
Tech LeadというRoleをもらった
2018/4から休職までの間、Tech LeadというRoleを任せられていた。
Tech Leadという言葉を出しちゃうと各位の俺の中のTech Lead
が一人歩きし始めてめんどくさいのでTech Lead業に関して語りたい人はぜひ飲みに行きましょう。受けて立つ。
やってみて実際どうだったかなと振り返ると、学びもつらいことも同じくらいあったなと思う。
自分はパーソナリティ的に人に頼るとか任せるということが本当に苦手なので人をうまく使えなかったり、頼ることができずに自分で自分自身に負荷をかけて自滅することがかなり多かった。
そんな感じで自滅してパフォーマンスが落ちたり、いわゆるやらかしをやってしまったことも多々あるが、それでも率直なフィードバックをくれ続けた上長や支えてくれた同じチームのエンジニアたちには本当に感謝しかないです。
それのおかげか、慣れてきてからはうまく負荷分散をしたり少し視点を引き上げて、自分がどうなるかより自チームがどうなるかを考える癖がついたのはよかった。
そうなったらそうなったでまた次の壁があったりするんですがそのあたりはメルカリにいる間に解決できず仕舞いなので次の場での宿題としたい。
WebDB+Press執筆参加した
若干裏話なのかもしれないけど、これはメルカリにいて「あいつ、設計周りうるさいらしい」みたいな感じで誘ってもらえた故に得られた機会でした。
とても楽しかったな、でも執筆は本当に大変でした。
買ってね!!!!!!https://t.co/mARp4hBVzH
— きりん / kirin (@sota1235) August 24, 2018
Web Rearchitect
2018年に元のチームを離れてからはずっとWebの作り直しチームにcommitしていた。
今まで取り組んだ仕事の中でぶっちぎりで抽象度が高くて、一番最初のステータスは「今のWebをいい感じのアーキテクチャに作り変えたい」ぐらいの粒度だった。
当然「なるほど?」となるわけで、初期は必死に変数集めをしていた記憶がある。
- 現状のシステムはどうなってるのか
- 作りかけの新システムはあるのか、あるならどういう感じなのか
- 会社のアーキテクチャ方針はどうなのか
- プロダクトとしての方向性はどうなのか
- Webチームの未来像はどうなりたいのか
- ビジネスとバランスを取った時のスピード感はどうなのか
こんなことを必死に考えてた。考えて問題を整理して解きほぐして分解して、最終的に出てきた「n年後のチーム、1年後のチーム、今の状態」の引き算をして、現実的な戦略に落としていった。
この過程が本当に暗中模索だし五里霧中だし、意思決定に迷い続けた記憶がある。迷い続けて周りにいる自分より圧倒的に強いエンジニアたちに相談しまくった。
思えば毎日が意思決定の連続で胃に穴が空きそうなことを決め続けていたと思う。でもそのおかげで技術的な意思決定を一定の品質を担保しながら最速でやること、決めきれない意思決定では未来を見据えて極限までリスクを減らした上で意思決定することができるようになったと思う。
毎日、意思決定をしていて意思決定力がめきめき伸びていく
— きりん / kirin (@sota1235) November 26, 2018
このあたりの能力は抽象度が高い課題でありながら決定権の大部分を会社が移譲してくれたからこそ身につけられたものだと思う。本当に感謝したい。
そして(私が把握してる範囲では)対外的に発表してませんが、メルカリWebのトップ画面は新しいアーキテクチャで動いています。
たった1ページに1年半かかってしまった(これは私の実力不足)けど、非常に難易度の高い要求を会社の荒波に揉まれながらも世に出すところまでこぎつけられたのは間違いなくチームメンバが優秀だったおかげです。
私はなぜかチーム運だけは異常にいいと自負しているのですがこの先、自慢できる最高のチームのうちの1つに今のWebチームは間違いなく入ると思います。
僕より強いBackendマンで興味ある人いたら声かけてください。絶対おもしろいと思わせる自信ある。
ISUCON9の運営やった
こればっかりはタイミングが合わないと参加できない活動なので本当に参加できてよかった。
その他いろいろ
- Splathonに参加できたのはよかった、もう参加できないと思うとさみしい
- 収入は引くぐらい上がった、たぶんこの先5年は同じ給料もらえないと思う
- し、環境も本当によかった。同じ給料、待遇、環境で働ける会社は当分ないだろう、欲しいなら作らないとだめだろうくらいに思ってる
- 障害対応力が異常についた、障害を起こしてしまっている、という裏返しでもあるが自チームでなくともある程度舵取りできるところまで成長できたのは本当によかった
- 上場をリアルタイムで経験できたのはエモかった
- 3年間で露骨に集中力が落ちてきた、年齢に反比例してパフォーマンスが下がらないための工夫を考えないとまずい
- 仕事じゃないけどRoppongi.js立ち上げたりした。近々復活の噂があるらしいので乞うご期待
- サービス立ち上げてコード書きまくってそれなりに評価してもらっても
俺は弱い
という感覚は全然抜けない、もっと強くなりたい…
その他Twitterから見つけた微笑ましい思い出たち
異国の地で心を落ち着かせるためにtweetしてる様子。
オフィスからそう遠くない場所で昨夜に発砲事件あったと聞いて笑ってる
— きりん / kirin (@sota1235) February 15, 2017
爆弾騒ぎでオフィス追い出された
— きりん / kirin (@sota1235) February 28, 2017
当時は言えなかったけど、社内賞をもらって実はかなり喜んでた様子。
BeProfessional賞なるものをもらいますたhttps://t.co/ruO4w6bhRK
— きりん / kirin (@sota1235) January 19, 2018
有志のファンにより出張の様子がトゥギャられたやつ。
ヘルニアで入院してる図。
入院中に見るはたらく細胞、趣深すぎる
— きりん / kirin (@sota1235) August 15, 2018
会社の開発合宿で温泉宿行ったのにヘルニア手術直後で温泉入れない図。
熱海で温泉入りながら負債返済をするっていう合宿なんですけど、術後1ヶ月温泉入れない私は部屋のシャワーです
— きりん / kirin (@sota1235) August 28, 2018
チームメンバーに飲み会でかけられた温かい言葉。
今日の名言「おいテックリード、焼きそばパン買ってこいよ」
— きりん / kirin (@sota1235) September 26, 2018
アイデンティティを確立した様子。
このキーワードで検索すると全部、私にまつわるページが一番上に来ます
— きりん / kirin (@sota1235) September 22, 2018
・aikoと結婚したい backend engineer
・14万円 飛行機
・isucon ビール禁止
今後
次の職場、という切り口で言うと特に決まってないです。副業しながら適当にのんびり過ごす予定です。
じゃあフリーランスになるのか、というとそういうわけではなくまぁ色々考えてはいるんですが焦って決めずにのんびり考えようという気持ちです。
こういうタイミングをpublicにすると飲みに行きましょう、とか弊社遊びに来ませんか、みたいなのがたくさん来がち(とか言って来なかったら馬鹿にしてくれ)だと思うんですけど、前述の通り当分はのんびりマイペースに過ごしたいので興味がないものとか知らない人とかからのそういうコミュニケーションはしばらく放置しがちだと思います。すいません。
色々決まったらまた雑に報告できると、特にメルカリでお世話になった人にはまたこれ頑張りますと言えたらいいなぁ。
一緒に働いてくれた方は内外問わず、本当に3年間お世話になりました!またいつかどこかで。
*1:今も変わらない文化と言ったが、昔と比べると規模が大きくなってるので能動的に自分のアウトプットをアピールしないと承認は降りづらくなってると思う。とはいえ普通にやってたら認めてもらえると思う。
2019年振り返り
去年
見返すと何も達成してなくて笑った
サマリ
- ライブ行きまくった
- ISUCON9の運営に参加した
- MP減って休職した
- 登壇しなかった
- 副業始めた
ライブ行きまくった
昔から音楽が好きで若い頃の一時期はライブハウスに通う日々を過ごしてたのだけど社会人になってからはあまり行ってなかった。
ただ、時間が経つにつれて名前を知ってるバンドが解散したりメンバーチェンジしたり、亡くなってしまうことが増えてきた。
特に去年はそういうのが多かったので年初に「人生で一度は見たいバンドのライブに全部行く」という目標を立てた。
結果、一回見て満足するどころかもう一回見たくなるし対バンやフェスで見つけた新しい推しのライブにも行き始めてしまって芋づる式にライブ本数が増えた。
上に全部書いたが実に47本のライブに参加した。満足。
来年もたぶんいっぱい行く。
ISUCON9運営に参加した
学びが深かった。
MP減って休職した
9-11月の間、MPが減って休職してました。
邪推されるのもめんどくさいんであんまopenにしてなかったんですが今は元気に復帰してるのでお気づかいなく…!
意外と休んでも人生どうにでもなるんで死にかけてる人はみんな休んでほしいなと思ってます。
登壇しなかった
去年は割とカンファレンスや勉強会で登壇する機会が多かったんですが今年は仙台PHPカンファレンスの一本だけでした。
理由として発表準備に時間をかけるよりインプットに時間を割きたかったのと、単純に飽きもなくはないです。
今年それなりにいろいろ勉強できた気がするので来年はちょいちょい話したいですね。
副業始めた
以前も副業をしてたことはあったのですが、今年は技術アドバイザーなるものを副業として始めました。
開発者としてでなく、アドバイザーとして副業をするのは初めてなので結構不安もあるのですが今の所それなりにうまく行っているんじゃないかなぁと思います(少なくとも頂いてる対価と同等以上の価値を出せてると信じたい)。
アドバイザーとなると基本的には自分が持つ知識やノウハウを価値として提供し続けることになるのですが、提供する一方で私自身も学びになることがとても多く、楽しくやれています。
このあたりも機会があれば言語化したい。
2020年
社会人になって5年経ち少々人生に飽きが出てきた感覚があるのでaikoのライブと同じくらい熱中してやれる何か(仕事でも仕事でなくても)を見つけられたらいいかなぁと漠然と思ってます。
今年もいっぱい迷惑をかけてみなさんに助けられた年でした、来年も引き続き助けてくれたら嬉しいです。
ISUCON9予選でフロントエンド周りの実装を担当した話
ISUCON9に参加した方、本戦までお疲れさまでした!
今年のISUCON9では運営として予選の作問に携わり、フロントエンド周りを担当しました。
その際に得た知見や実装なりの話を雑に書こうと思います。
話で出てくるソースコードは全てここにあります。
Excuse
- 個人としての雑記です
- 本業フロントエンドエンジニアではないので詰めが甘い部分がかなり多いです
- 本業フロントエンドエンジニアからのマサカリ待ってます
- ISUCON運営として作るフロントエンド、という視点で書いていきます
- 願わくば未来のISUCONフロントエンド担当者に届け
あとは講評や解説は公式Blogで出してるのでそのあたりをぜひ読んでください!
あとはBackendやベンチマーカーの実装に関しては@catatsuyさんの記事とGitHubのコードを合わせて読むことをオススメします。
私とISUCON
私自身のISUCONとの関わりはこんな感じです。
- ISUCON5から毎年参加している
- 毎年予選落ちで地団駄を踏む
- 去年は覚悟を持って望んだものの予選落ち、ビール禁止を決意する
といった感じでした。
今年ももちろん再挑戦、悲願の予選突破を目指そうと思っていたのですが自分の会社に作問が回ってきたのでこんなチャンスなかなか無いだろうと思い運営として参加しました。
技術スタック
アプリケーション自体、どれくらいフロントエンドを作り込むかの点に関しては後述する理由でSingle Page Application(SPA)を採用しました。
私自身、以前にSPAを作ってからかなり年月が経ってしまっていたのと、今回は多少小回りが効かないとしても動くことが最優先だったのでcreate-react-appを利用しました。
丁寧にテストを書く余裕はないだろうと想像できていたのでなるべくエンバグしないようTypeScriptも導入しています。
create-react-appを最後に触ったのは2年ほど前だったのですが、その時よりもかなり使いやすくなっていて最高でした。
no config(厳密には違うのかな)でhot reload、transpile等々動くのは楽だしソースコードと設定周りが強く依存し合うこともないので個人的に重視している捨てやすさも十二分にあるなという印象です。
これに合わせてState管理周りはRedux、UI周りはMaterial UIを導入しています。Material UIマジで最高。
他に使ってるものは興味あればpackage.jsonを覗いてください。
フロントエンドの方針
以下の点を方針として立てました。
- Backendのテンプレート移植の負担をなるべく無くす
- 競技者がアプリケーションを理解しやすいフロントエンドを作る
- 機能が理解しやすい
- 壊れたときに原因がわかりやすい
- フロントエンドでデバッグしたいときにやりやすい
Backendのテンプレート移植の負担をなるべく無くす
ISUCONでは例年、多くの参加者が楽しめるよう複数の言語実装を提供しています。言い換えるとブラウザで開くと全く同じに見えるアプリケーションを複数種類の言語で実装するということです。
その際、コストとして大きいのがHTMLレンダリング周りの移植です。
Backend側での実装移植はよほど言語に依存した実装にしていなければ難しくないですが、テンプレートエンジンは言語やライブラリによって機能の差異が多く結構大変です(※過去の運営をやったわけではないですが、一緒に運営をした人の体験談から想像するのは難くなかった)。
なので基本、Backend側はHTTPのAPIを提供するのみ、HTMLのレンダリングはブラウザ上でする、という方針になりました。ゆえのSPA。
競技者が機能を理解しやすい
今回のアプリケーションは一言で言うならば椅子のフリマアプリでした。
近年は様々なフリマアプリが使われるように身近に感じられるようになりましたが、とはいえ競技者全員が直感的に機能を理解できるとは限りません。
特に今回は配送機能や決済機能周りはAPIのI/Fや仕様書のみから全てを読み解くのは容易ではなかったので、フロントエンドの画面を触ることでそれぞれのAPIの存在意義や機能を理解できるよう心がけました。
このあたりは以下のissueで議論しました。興味があれば覗いてみてください。
壊れたときに原因がわかりやすい
参加したことがある方はよくわかると思いますが、ISUCONでは初見のアプリケーションを壊さずにドラスティックに書き換えていく必要があります。
その過程で起こる問題として意図しないエンバグやその原因調査です。
フロントエンドではこのあたりにすぐに気付けるようにし、原因調査のヒントとなるようにすべきです。
それにあたり以下のような方針で実装しました。
- ページレンダリング時にcriticalなエラーがAPIから返ってきたらAPIのエラーメッセージを500ページにそのまま表示
- フォーム等でエラーが返ってきたらMaterial UIのSnackbar Componentを利用してAPIのエラーをそのまま表示
現実のアプリケーションではAPIのエラーをそのまま表示したり、criticalなエラーを全て500として扱うことは望ましくないのですが今回は競技者にいち早くエラーに気づいてもらう&エラー文をDeveloper Tool等を見ずに知ってもらうためにこのような構成にしています。
BUMP機能のフィードバックUI追加 by sota1235 · Pull Request #411 · isucon/isucon9-qualify · GitHub
フロントエンドエラー周り修正 by sota1235 · Pull Request #299 · isucon/isucon9-qualify · GitHub
ログイン/新規登録時のエラー表示方法を変更 by sota1235 · Pull Request #417 · isucon/isucon9-qualify · GitHub
その他工夫したこと/ハマったこと
React Routerで同ページ間の遷移もActionが発火する
今回はReact RouterをReduxにつなぎこむためにsupasate/connected-react-routerを利用しました。
このconnected-react-router
はReact Routerでページ遷移が発生した際に@@router/LOCATION_CHANGE
というActionを発火させます。
このActionを見ることで例えば「商品ページから別ページへ遷移したら商品ページのstateを初期状態に戻す」といったことが可能になります。
私のState管理の実装は以下のようになっていました。
- Page Componentのレンダリング時(
constructor
)にデータをfetchするためのActionを発火- データが来るまではloading componentを表示しておく
- React Routerのページ遷移アクションが発生したらデータとローディングステータスのstateをリセット
しかし、このActionは同じページ間を遷移する場合にも発火してしまいます。
結果として
- ユーザからはページ遷移していない(同じページにとどまっているだけ)のにデータリセットのが走る
- Page Componentはレンダリングされない(既にされている)のでデータfetchは走らない
というバグが発生しました。
対応策として、@@router/LOCATION_CHANGE
が発火したら遷移前のpathと遷移後のpathを比較し、違う場合のみカスタムActionを発火するmiddlewareを実装。それをもとにState制御することで解決しました。
import { Dispatch, Middleware, MiddlewareAPI } from 'redux'; import { AppState } from '../index'; import { LOCATION_CHANGE } from 'connected-react-router'; import { pathNameChangeAction } from '../actions/locationChangeAction'; import { ActionTypes } from '../actions/actionTypes'; // react-routerのページ遷移発火時、pathnameが変わった場合は独自のactionを発火する const checkLocationChange: Middleware = <S extends AppState>( store: MiddlewareAPI<Dispatch, S>, ) => (next: Dispatch<ActionTypes>) => (action: ActionTypes): any => { const { getState, dispatch } = store; if (action.type !== LOCATION_CHANGE) { return next(action); } const { router } = getState(); const currentPath = router.location.pathname; const nextPath = action.payload.location.pathname; // 遷移前と遷移後が同一pathなら何もしない if (currentPath === nextPath) { return next(action); } dispatch(pathNameChangeAction()); return next(action); }; export default checkLocationChange;
タイムラインのバグ修正 by sota1235 · Pull Request #285 · isucon/isucon9-qualify · GitHub
同一Routeで異なるpathへの遷移時のState管理がうまくいかない
先程の実装で十分かと思いきや、まだカバーできないパターンがあります。
例えば/items/:item_id
というRouteがある際に、/items/8
から/items/9
へ遷移したパターンです。
このパターンの際に起きるバグとして
/items/8
へアクセス- Page Componentがレンダリング、constructor内でfetch Actionが発火
- ページレンダリング完了
/items/9
へ遷移- ページ遷移のカスタムアクションが発火
- stateがリセットされる
- しかしPage Componentは再レンダリングされないため、fetch Actionが発火しない
これを解決するためにReact ComponentのgetDerivedStateFromProps
メソッドを利用しました。
static getDerivedStateFromProps(nextProps: Props, prevState: State) { const nextLoading = nextProps.loading; const nextPageUserId = Number(nextProps.match.params.user_id); // ページ遷移を確認した場合はデータ取得を行う if (nextPageUserId !== prevState.currentPageUserId) { nextProps.load(nextPageUserId, nextIsMyPage); return { ...prevState, loading: true, currentPageUserId: nextPageUserId, }; } return { ...prevState, loading: nextLoading, currentPageUserId: nextPageUserId, }; }
上記のnextProps.match.params.user_id
には例えば/users/:user_id
というRouteにアクセスした際に:user_id
に入る任意の値が入ります。
これにより同じRoute間の遷移、かつ違うpathでも正常に動作するようにできます。
Material UIのtheme styleがうまく反映されない
Material UIにはBase Colorやfont-size等をglobalで統一して管理したいときに便利なTheme機能があります。
今回も色の調整等でこの機能を利用していたのですが、特定のページの一部コンポーネントにスタイルが適用されないバグがありました。
色々調べていくと同じバグに遭遇してる人は何人か見つけたものの、どの方法を試してもうまく修正できなかったのでバグが再現するコンポーネントにのみnesting themeを同じテーマを使って行うというハックでバグを回避しました。
Special thanks
今回、きちんとSPAを作り込むにあたり主にデータローディング周りの設計に結構悩まされたのですが、私のggり方が悪いのか体系的に解説したいいドキュメントや記事を見つけられませんでした。
自分で車輪を再発明するしかないかと諦めかけましたが、藁にもすがる気持ちで@hiroppyのソースコードを読みにいったら抱えてた疑問や迷いに対する答えが全てありました。
いろいろ調べた挙げ句 @about_hiroppy の書いたコード読みに行ったら一発で解決。ありがとう僕たちの @about_hiroppy
— きりん (@sota1235) August 3, 2019
最後に
ISUCON9予選に参加して競技を楽しんでくれた皆様、メルカリの出題チームのメンバー、そして運営の皆様、本当にありがとうございました!
来年は(きっと)参加者として予選参加して本戦に行きたいと思います。