【オフライン開催】Urawa.rb #1 - connpass
Urawa.rb #1に参加しました
こちらのUrawa.rb(浦和Ruby)に参加しました。
記念すべき第一回に立ち会うことができて良かったです!!
ボードゲームもとても楽しかったです。
お話ししてくださった皆様、ありがとうございました。✨
【オフライン開催】Urawa.rb #1 - connpass
こちらのUrawa.rb(浦和Ruby)に参加しました。
記念すべき第一回に立ち会うことができて良かったです!!
ボードゲームもとても楽しかったです。
お話ししてくださった皆様、ありがとうございました。✨
嬉しいねぇ🌿🤩
こんにちは! これはフィヨルドブートキャンプ Part 1 Advent Calendar 2023 - Adventarの4日目の記事です。 昨日のエントリーは、suzuka_horiさんの「「FBCビブリオバトル」で発表した感想📚 - すずかのプログラミング勉強記」でした!
本日のエントリーでは、WebSocketについて具体的なコードを交えながら世界一わかりやすく解説していきたいと思います!
WebSocketとは、サーバーとクライアント(ブラウザ)との間で双方向通信を行うための通信プロトコルです。
一番わかりやすい例では、チャットアプリが挙げられます。
相手が送ったメッセージをリアルタイムに眺めるためには、クライアントA → サーバー → クライアントBへと即座に送る必要があります。
WebSocketなら双方向通信が可能なので、この機能を簡単に実装できます。
また、多人数対応のオンラインゲームを作るときにも役立ちます。
Node.js+Socket.IOで作る、通信対戦ができるHTML5ゲームシステムの作り方 - Yahoo! JAPAN Tech Blog
この技術を使うことで、サーバーから送信されたメッセージをクライアントがいつでも受け取れるようになります(逆もしかり)。
HTTPの場合、クライアントがサーバーに「自分宛てのメッセージが届いていませんか?」と一定間隔で問い合わせる必要があります。この方法だと、リアルタイム性が失われてしまいます。通信ごとに、一回一回コネクションが切れています。
WebSocketの場合、接続を切るまでずっとコネクションが繋がったままです。専用の軽量なプロトコルを用いて、安定した通信を維持できます。
ここからが本題です。
WebSocketという名称を聞いたことがあっても、実際にどんなふうにコードを書けば良いのか迷ってしまうかもしれません。
そのため本記事では、自分が作成した「世界一わかりやすいWebSocketのサンプルコード」を用いつつ、そのコードを解説していきます。この記事とリポジトリのコードを読めば、基本をガッチリ押さえられるはずです。
lef237/simple-websocket-typescript: シンプルなWebSocketのTypeScriptコード
こちらのリポジトリを用意しました。
このコードを用いつつ、どのような流れでメッセージが送受信されているか解説します。
まず、上記のコードを実行しましょう。実際に動く様子を見ることで、その後の解説が分かりやすくなるはずです。
実行方法はREADMEに書きました。📝
本当は試しに動かして頂きたいですが「手元で動かすのはちょっと面倒……」という方向けに、録画した動画を添付致します。
https://youtu.be/j9_ARlt6X2w?si=IpVTTzuazrSY6V18
左のウィンドウがサーバーで、右の2つのウィンドウがクライアントです。
aaa
, bbb
といった文字列がリアルタイムに送受信されたのをご確認頂けたと思います。
まず、クライアント側のコードから説明していきます。
リポジトリにはNodeとBunのディレクトリがありますが、Nodeのほうで解説していきます。
simple-websocket-typescript/node-websocket/client.ts at main · lef237/simple-websocket-typescript
http://
ではなくws://
を使おうWebSocketの通信にはws://
またはwss://
から始まるURLスキーマが必要です。
それぞれhttp://
がws://
, https://
がwss://
に対応している感じです。
今回はローカル環境内での通信のため、ws://
のほうを使うことにします。
(本番環境ではwss://
を使いましょう!)
const url = "ws://localhost:8080";
先ほどのurl
を使ってws
インスタンスを生成しています。
const ws = new WebSocket(url);
このws
インスタンスに対してサーバーからイベントが送られます。
下記の4つのイベントごとに、クライアントで処理を実装できます。
onopen
→ WebSocketコネクションが確立したときに実行するよonmessage
→ サーバーからデータを受け取ったときに実行するよ。受け取ったデータの値を確認できるよonerror
→ 何か問題が起こったときに実行するよonclose
→WebSocketコネクションが閉じたときに実行するよちなみに自分はonmessage
のような書き方(イベントハンドラープロパティ)にしましたが、addEventListener()
メソッドを使うこともできます。
ws.addEventListener("message", (e) => { console.log(`Received: ${e.data}`); promptInput(); });
この書き方でも問題なく動きます!
詳しくはMDN Web Docsを参照ください。
WebSocket: message イベント - Web API | MDN
今度はクライアントからサーバーへと指示を送るときです。
具体的には次の2つのメソッドが使えます。
send()
→ サーバーへとメッセージを送りたいときclose()
→ WebSocketコネクションを切断したいときリポジトリのコードでは、次のようになっています。
function promptInput() { rl.question("Enter message to send: ", (message) => { if (message === "exit") { // 'exit'と入力した場合、プログラムを終了 rl.close(); ws.close(); } else { ws.send(message); } }); } ws.onmessage = (e) => { console.log(`Received: ${e.data}`); promptInput(); };
まず、onmessage
でサーバーからのデータを受け取っています。そして、データを受け取ったらpromptInput()
関数を呼んでいます。
promptInput()
関数では、readline
を使ってターミナルでの入力を受け付けています。
question()
関数では、エンターキーを押したときにコールバック関数(アロー関数の部分)が呼び出されて、直前に入力した文字がmessage
変数へと渡されます。
そして、このmessage
変数(入力された文字列)が"exit"
のとき、WebSocketのコネクションを切断します。それ以外のときは、そのmessage
変数に格納された文字列をサーバーへと送るようになっています。
一見複雑に見えますが、単純にws.send(message);
でサーバーへとメッセージを送ってるよ〜と理解すると分かりやすいと思います。
次にサーバー側のコードを解説していきます。こちらもNodeで解説します。
simple-websocket-typescript/node-websocket/server.ts at main · lef237/simple-websocket-typescript
サーバー側の詳しい書き方については、wsライブラリのREADMEをご参考ください。
こちらのリンク先のSimple serverを元に説明します。
import { WebSocketServer } from 'ws'; const server = new WebSocketServer({ port: 8080 }); server.on('connection', function connection(ws) { ws.on('error', console.error); ws.on('message', function message(data) { console.log('received: %s', data); }); ws.send('something'); });
このコードのように、on
とsend
を使うだけでほぼ目的は達成できます。
server.on()
を使って、第一引数に"connection"
、第二引数にコールバック関数を渡しています。これで、サーバーへのコネクションが確立されたとき、クライアント側から送られたメッセージの処理をおこなえます。
あとはws.on()
を使って、message
が送られたときの処理を実装します。
この中でconsole.log()
を使ってログを出力したり、send()
を使ってクライアント側にメッセージを送ったりします。
ws.on('message', function message(data) { ws.send(`Client said: ${data}`) });
このように書けば、サーバーが受け取ったデータをそのままクライアントに投げ返すことができます。
これで、双方向通信が可能になりました!
しかし、ちょっとだけ物足りないです。
WebSocketを使えば、一つのサーバーに対して複数のクライアントが接続できます。
複数のクライアントを接続できるのだから、クライアントAが送信したメッセージを、クライアントBも受け取れるようにしたいです。
【現在】
【理想】
理想形のほうが、実際のチャットアプリに近いです。
この挙動を実現するために、サーバー接続時に生成されたws
(WebSocketのインスタンス)を、Set
を使って保存しましょう。
そして、それらのインスタンスの集まりをclients
とし、forEach()
関数でその全てにメッセージを送ればOKです。
const clients = new Set<WebSocket>(); // 接続中のクライアントを格納するSet server.on("connection", (ws) => { clients.add(ws); // クライアントを追加 ws.on("message", (message) => { // すべてのクライアントにメッセージをブロードキャスト clients.forEach((client) => { client.send(`Client said: ${message}`); }); }); });
まずターミナルでサーバー側のコードを動かします。
それからChromeのDevToolsでコンソールを開きます*1。
ブラウザから送信する場合、Node.jsとは違ってクライアント側でWebSocketのライブラリを用意する必要はありません。
ちなみにライブラリを使った場合、Set
を使わなくてもBroadcastすることはできます。
https://github.com/websockets/ws#server-broadcast
今回はBunのコードとなるべく形を揃えるため、Set
を使って実装しました。
(Bunの場合はpub/subで実現できるようです)
今回は文字列を送受信しているだけですが、オブジェクトやJSONを使うことでもっと複雑なdataを受け渡すこともできます。
例えばオンラインゲームで、キャラクターに対して指示を出すdataをイメージしてみましょう。
const data = JSON.stringify({ target: "lefzou", action: "move", direction: "right", ... });
サーバーを介して複数のクライアントがこのdataを送受信すれば、お互いのブラウザに描画されたキャラクターをリアルタイムに動かせるでしょう。
WebSocketの簡単な使い方について今回ご紹介致しました。
必要最小限の機能を満たすように、コードをなるべくシンプルに保つように気をつけました。記事の説明で分からないところがあっても、GitHub上のコードを読めば、大方のところは理解できるようになっていると思います。
Bunで実装したコードもリポジトリに上げています。そちらについても解説しようか迷ったのですが、この記事の主旨から外れそうなので今回は断念しました。ぜひNodeのコードと見比べてみてください。
MDN Web Docs以外では、JavaScript Infoさんの記事がオススメです。
https://ja.javascript.info/websocket
明日のエントリーは Sochi419 さんの記事です! 楽しみ✨
*1:ブラウザを右クリックして「検証(Inspect)」を選択します
※かなり短いゆるめの記事です。
この記事の着想はmasakinihirotaさんのツイートからアイデアを得たものです! ありがとうございます!
Next.jsは「Reactのプラスα」的な使い方をすれば、個人開発の規模感でも使いやすい。
個人開発の用途でNext.jsに触れているのですが、バージョンが上がるに従ってどんどん新しい機能が増えていて、キャッチアップに困っていました。
具体的には、ねりけしさんのこのツイートと同じ悩みを抱えていました。
ねりけし @nerikeshi_k
個人開発物Next.jsで作ってるけど日和ってpage routerにしてしまっている。個人開発物ならばapp routerを試すべきでは とも思いつつ、でも自分のモチベは限りある資産(?)だから、技術的な挑戦はリリースまで辿り着けそうな上限に絞る必要があると信じているので、日和ってしまってる(二回言う)
https://twitter.com/nerikeshi_k/status/1715357927383716284
App Routerを使うかPage Routerのままにするか、Server ComponentsとClient Componentsをどのように使い分けるか、Server Actionsを導入するか……覚えることがたくさんあって混乱していました。
Reactについては「ちょっとデキる」ですが、Next.jsについては「何もわからん……」という状態でした。*1
任天堂の横井軍平さんの名言に「枯れた技術の水平思考」という言葉がありますが、これは個人開発にも当てはまります。ある程度落ち着いている技術のほうが、素早く開発できます。
技術的挑戦はとても大事です。しかし、「一つのプロダクトを自分一人で最後まで作り切る」という目標の達成においては、ある程度落ち着いた技術のほうが開発しやすいのも事実です。
そんな中、偶然見つけたのがmasakinihirotaさんのツイートでした。
masakinihirota @masakinihirota
Next.jsで高性能にする意味がないなら page routerのままでいいと思う。最先端の機能が使いたい、高度なことに挑戦したいというのならApp routerを使えばいいと思う。もしくはrootに'use clinet' ディレクティブ置いて全部クライアントにすればいいんじゃないかな?
App routerのディレクトリでのルーティングのほうが直感的で使いやすい。 App routerは、真面目に使おうと思うとかなり高い壁になるとおもう。サーバークライアントはもちろんmiddlewareとかも絡めて考えなきゃいけなくなるからね。
https://x.com/masakinihirota/status/1710969004972703751?s=20
このツイートは自分にとってコロンブスの卵のようなツイートでした。
このおかげで、自作サービスにおけるNext.jsの開発方針を決定できました。
戦略はとてもシンプルです。
まずはClient Componentsのみでアプリを作ってみます。
つまり、App Routerの状態でトップレベルのコンポーネント(root)にuse client;
をつけて、全てのコンポーネントをいったんClient Componentsにします。
開発を進めていけば、自然と静的に表示したい箇所が増えてくるはず。
そこから徐々にServer Componentsの領域を増やしていけばOK!
データの取得方法も、useSWR
を使ってまずはCSR(クライアントサイドレンダリング)から始めてみるのがオススメです。*2
すごく単純なフローですが、このことに気がつくまで色々悩んでかなりの時間を費やしました。
ここから導き出せる一般法則は「新しい技術に触れるとき、まずは自分の詳しい領域のみを使って開発しよう」ということです。そして基本をガッチリと固めてから、徐々にエッジな技術を取り入れてみるのが良さそうです。
最近Rustについて調べていたときに @sadnessOjisan さんのこのツイートを見掛けました。
統合開発環境 @sadnessOjisan
Rust, 正直なところウェブサーバーを書くための言語としてならかなりイージー側の選択肢だと思うんだよな。所有権とかライフタイム無視して書いてもお釣りが来ると思うし、実はそんなに勉強しなくても書けると思う。DB周りの扱いはクセあるけど、それはどの言語も同じでしょとも思う。知らんけど。
https://x.com/sadnessOjisan/status/1726408490649006312?s=20
このツイートも慧眼だと思いました。つまり、所有権やライフタイムをすぐに使いこなせなかったとしても(Rustの全ての機能を使いこなせなかったとしても)、まずは自分の分かる範囲で使うだけでもメリットを享受できるということです。
新しい技術やスピードの速い技術に触れるとき、ついつい全てを理解してから触れてしまいがちですが、そんなに気負うことはなくて、まずは自分が理解しやすい範囲で使ってみる、というのが良いのだと分かりました。*3
話を戻すと、まずはCSR的な用途のみで使うことで最新のNext.jsでも安心して使えるのがこの開発方針のポイントです。
個人開発でNext.jsを使いたい方のご参考になれば幸いです。
ちょっと追記(2023-11-28)
以前、ブログ記事に「T3 Stackを使って開発をしてやるぜ!」みたいな内容のことを書いたのですが、これはこれで色々なデメリットが有ることが分かりました。
というのも、T3 StackはPage RouterとAPI Routesを前提にして作られています。*4
それぞれのライブラリがPage Routerと密結合している印象を受けました。自分はT3 Stackを使って途中まで開発していたのですが、Page RouterからApp Routerへの移行があまりに複雑で、素のNext.jsを使ってゼロから作り直すことにしました。
またtRPCはAPI Routesが前提になった作りになっていて、Route Handlersでは実装できません。
そして最新のNext.js公式は、API RoutesではなくRoute Handlersを推奨しています。
Good to know: If you are using the App Router, you can use Server Components or Route Handlers instead of API Routes.
API Routes can't be used with static exports. However, Route Handlers in the App Router can.
そのため、T3 Stackを使った状態でNext.jsのバージョンを上げたとき、最新の機能に合わせてコードを書き換えるのが難しいです。*5
これはNext.jsの技術の進展が速いことが理由です。つい先日まではAPI Routesを新機能として勧められていた気がするのに、いつの間にかRoute Handlersが推奨になっていました。
Next.jsの技術の進化は素晴らしいと思いますし、なんだかんだとても使い勝手は良いです。ただ、最新の機能をキャッチアップしすぎると、それだけで時間が溶けてしまい、肝心のプロダクト開発・機能追加に着手できないという問題があります。最近の個人開発のトレンドを見ても「Next.jsのApp Routerを諦める選択」は割りと多く見られる気がします。
つまり、何が言いたいかというと「ある時点でのNext.jsを前提にした技術スタックの塊」を使ってガチガチに構築すると、アップグレードが大変になるということです。
App RouterやServer Components, Server Actionsへの移行をスムーズにするには、外部のライブラリを使いすぎないという選択肢もアリだと思います。自分はそうするつもりです。
そのため、Next.jsの進化がもうちょっと落ち着くまで*6、App RouterでClient Componentsを使うCSRを中心にした薄めのフロントエンドにしたほうが色々と困らないのではないかと思いました。Reactの基本的な機能に絞って使ったほうが、後々の開発で助かる気もします。*7
余談ですが、ReactやNext.jsがどのような歴史を辿ってきたのかについては、この記事に詳しくまとめられていてとてもオススメです。
Next.jsから学ぶWebレンダリング ~React誕生以前からApp Router with RSCまでの流れ~
*1:ViteでのReact開発や、Deno/FreshのPreactでの開発はしたことがありましたが、それでもNext.jsはよく分からない状態でした。Island Architectureより難しい気がします
*2:Next.jsの場合、CSRのデータ取得でuseEffectかuseSWRを使いますが、後者の方をオススメします。詳細はこちら → https://nextjs.org/docs/pages/building-your-application/rendering/client-side-rendering
*3:まずは理解しやすいところから始めて、徐々に知見を広げていく
*4:T3 StackでApp Routerを使うオプションが最近導入されましたが、まだExperimentalです。
*5:Page RouterやAPI Routesを最新のNext.jsでも使えるため、あえてそのままにすることもできますが、個人的にはなんとなく居心地が悪いです……
*6:Server Componentsの機能はReactが将来実装する機能の先取りなのでガンガン使っても大丈夫だとは思います → https://ja.react.dev/reference/react/use-server また、使いこなせるかは別としてServer Actionsも個人的には大歓迎です。
*7:もちろん、これは個人開発における考えです。フロントエンド専門のチームがいる場合は、色んなStackをどんどん積極的に取り入れるのも悪くないと思います。
最近Next.jsとPrismaとSupabaseとNextAuth(Auth.js)*1を組み合わせて認証機能を実装しようとしていたのですが、困ったことがありました。
それは、ローカルで立ち上げたアプリでは認証できるのに、リモート(本番環境)で立ち上げたアプリでは認証がうまくいかないという問題です。
リモートで認証しようとすると、リダイレクトの画面で「別のアカウントで試してね」という表示が出てきてログインできません。
開発環境としては次のようになっていました。
ネットで検索してもあまり情報がなかったので、今回ブログにまとめてみました。
問題箇所を特定するために、次のステップを踏みました。
NextAuthでGoogle認証ができるように設定していたところ、ローカル環境では問題なく認証できるのに、本番環境では認証できないという問題に遭遇する。 ↓ 初めはGoogle側で自分が何か設定ミスをしているのかもしれないと考えていたが、本番環境ではDiscordの認証までできなくなっていることを確認する。 ↓ NextAuthまたはVercelまたはSupabaseの問題であると絞り込む。 ↓ 更にローカルではエラーが再現しなかったため、VercelかSupabaseかの問題であることまでを絞り込む。 ↓ VercelおよびSupabaseのログを読み、データベースとの接続が怪しいと当たりをつける。 ↓ ローカル環境でもエラーを再現しようと試みる。 ↓ ローカル上のNext.jsのenvファイルの環境変数を変更し、ローカルからリモートのSupabaseに接続を変えたところエラーが再現する。 ↓ Vercel側の問題ではなく、Supabase側の問題だと特定する。 ↓ SupabaseとPrismaのドキュメントを読んでコネクションプーリングの設定をしたところ、無事に本番環境でもGoogle認証ができるようになる。
これで、無事にリモート(Vercel上のNext.js)でも認証機能を実装できました。
ここからは推測ですが、Prismaの機能をフルで使うためにはこの設定が必要なのだと思われます。
Using Prisma with Supabase | Prisma Docs
We strongly recommend using pgbouncer in addition to DIRECT_URL. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling.
Prisma schema API (Reference) | Prisma Docs
Connection URL for direct connection to the database. If you use a connection pooler URL in the url argument (for example, if you use the Data Proxy or pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the directUrl argument. The directUrl property is supported by Prisma Studio from version 5.1.0 upwards.
Supabaseのログを見ると、「pgBouncer
がうまく機能していない」というような内容でした。
そしてPrismaは「pgBouncer
を使うためにはdirectUrl
を使ってデータベースに直接接続する必要がある」とドキュメントに書いています。
逆にローカル環境同士でうまく動いたのが謎ですが、おそらくローカルで動くSupabaseとリモートで動いているSupabaseで中身がちょっと違うのだと思います。
コネクションプーリングは(すごく簡略化して説明すると)「ずっと接続を維持しておくための仕組み」なので、リモートでは接続が切れやすい設定になっているんじゃないのかな〜と思いました。
ローカルでは問題なく動くのに、リモートでは動かない事象に遭遇してとても不思議でした。
エラーの発生箇所を徐々に絞り込むことで解決できたので良かったです。
問題を解決するためには、確実に動いている地点を確かめるのが大事だと改めて理解しました。
また、BaaS(Backend as a Service)を使う場合には、リモートとローカルで環境を分けると設定が色々大変なことが分かりました。
(Supabaseを使った開発フローについてもそのうち記事を作りたいと思います。)
設定方法については次のリンク先の記事をご参考ください。
PrismaとSupabaseの公式ドキュメントです。
記事に従ってConnection Poolingの設定までおこなえば無事に動きます。Vercel側にも環境変数を設定してあげましょう。
*1:最近NextAuthからAuth.jsに名前が変わったらしい
皆さんはデザインが得意ですか? 自分は苦手です。最近だとTailwind CSSを使ってWebページにデザインをつけているのですが、なかなか難しいです。
というのも、プログラムのコードとは違って「正解」がないように思えるからです。
しかし、プロの方のデザインを見ていると、素人の自分とは明確な差異があります。その差異には理由があるはずです。
その理由を探るため、この『ノンデザイナーズ・デザインブック』を読んで確かめてみることにしました。
この本には4つの原則が述べられています。
どういうことかというと、関連する項目が近くにあって、ページ内の配置が揃っていて、同じパターンが繰り返されていて、違いがハッキリしていることが、良いデザインの基本だと述べられています。
と言われても、この文章を読んだだけではピンと来ないかもしれません。
この本はカラー刷りになっていて、良い例と悪い例のデザインの実例が紹介されています。文章をあまり読まなくても、該当のデザインをパッと見ただけで、どれだけの効果があるか分かります。百聞は一見に如かず、です。
一言でいうと、ユーザが分かりにくいデザインは良くないです。
上の4原則を守っていないデザインは、その画面が何を伝えたいかが分からず、ユーザを混乱させます。
例えばWebアプリで考えてみましょう。そのアプリでは、サービス名と操作ボタンが重要だとします。
それにもかかわらず、ボタンの大きさがバラバラだったり、どこにあるか分からなかったら困るでしょう。また、サービス名が目立たないフォントだったら、名前を覚えてもらえないかもしれません。
Webアプリにおける良いデザインは何か考えてみましょう。それは、一瞬で使い方が分かるデザインです。
説明書きをほとんど読まず、アプリに関する知識が皆無でも、迷わずサクサク操作できる。これは間違いなく良いデザインです。
画面が心地よくて、思わずサービスに登録しちゃった! ここまでいけば最高のデザインでしょう。
私達はあらゆる情報が次々に流れていく情報社会を生きています。そのため、1つの画面を長時間見ることはできません。
このブログですら、目次をさらっと読まれているだけかもしれません。最初から最後まで読み通している人はいないでしょう。
しかし、こうして重要な所を目立たせるだけで、少なくともそこだけは注意を向けてもらえます。
太字で目立っている部分を読むだけで、内容が推測できる。
こうすれば斜め読みするユーザにも情報を伝えられます。また、通読してくれるユーザも情報処理がしやすくなるでしょう。
目立つ部分と目立たない部分のコントラストを設けることは重要なのです。
これは本書には書いていない私見なのですが、デザインの良いWebアプリは、それだけで競合に勝てる要素を持っている気がします。
というのも、今まさに自分が使っているこの「はてなブログ」は、あらゆる面でUI/UXが優れています。
例えば、この文章を執筆してる編集画面は、何をどう操作すれば良いのかが一目瞭然です。他のブログサービスも使ったことがありますが、自分がはてなブログを使っているのは、この操作性と明瞭さにあります。
また、自分が大好きなサービスにZennがあります。Zennのデザインは本当に素晴らしくて、記事投稿系のサービスでは1つの到達点だと思います。
上に挙げた4大原則を、Zennは全部活用しています。また、細部の使い心地も良いです。
このように、長く生き残っているサービス、そして人気のあるサービスは、良いデザインであることが多いです。
良いデザインであれば、繰り返し使われ、ユーザの滞在時間も長くなるでしょう。悪いデザインであれば、どんなにサービスが良くても、長期間にはユーザが少しずつ減っていくかもしれません。
この『ノンデザイナーズ・デザインブック』についてGoogleで調べていたところ、とても素晴らしいスライドを発見したのでご共有します。
read-a-non-designers-designbook - Speaker Deck
本の内容を、別の文献も用いつつ、科学的根拠から裏付けています。
それだけでなく、このスライド自体がとても良いデザインになっています。次に発表スライドを作るとき、参考にしたいと思います!✨
※ちなみにフィヨブー関係者なら全員必読だと思います。理由は秘密です。
以前、とある飲み会でプロのデザイナーさんとお話ししたところ「UI/UXには正解があるんだよ」と仰っていました。
この本を読んだことで、その「正解」が何か分かった気がします。
つまり、ユーザにとって親切であること。言い換えれば、素早く明快に情報が伝わるデザインこそが1つの正解だということです。
そのための方法論を学ぶことができるのが、この『ノンデザイナーズ・デザインブック』でした。
デザインを学ぶ第一歩として、この本をオススメします。今まで無意識に捉えていたデザインの良し悪しを、具体的な事例とともに身につけられると思います。🎨
Reject on Rails2023 - connpass
このイベントのことです!
Gotanda.rbが主催していて、Kaigi on Railsで発表できなかった内容を発表できるイベントでした。
当日のツイートまとめはこちら → Reject on Rails2023 #rejectonrails - Togetter
今年、自作サービスをリリースしたのですが、その内容についてオフラインで発表する機会がなかなか見つかりませんでした。
「あ、そうだ。Kaigi on Railsにプロポーザルを出そう!」と決心したときには、8月2日。もう申し込みが終わっていました。
何かしらRailsに関係するイベントで発表したいな〜と思ってConnpassを探していると、Reject on Railsを見つけました。そこには「Kaigi on Railsで登壇したかったけれど、申し込みが間に合わなかった内容」も歓迎と書かれていました。
こりゃもう発表するっきゃない!ということで申し込みました。
『Rails 7でReactとHotwireを同時に使って個人開発して得た知見』というタイトルで発表しました。
登壇時に使ったスライドはこちらになります。
Rails 7でReactとHotwireを同時に使って個人開発して得た知見 - Speaker Deck
会場はこのような雰囲気でした(人が入る前の様子)。軽食やお菓子、特製ビールもあって良かったです!✨
とても楽しかったです! 前日から緊張してずっと心臓がドキドキしていたのですが、無事に発表を終えることができました。
個人的にとても嬉しかったのは、お集まり頂いた方からリアクションを貰えたことです。スライドの途中で拍手があがったり、内容について感想を頂けて、オフラインで参加することの醍醐味を感じることができました。
他の方の発表も勉強になりました。RubyやRailsに関して、まだまだ分からないことがたくさんあるんだな〜と改めて思いました。
プログラマーとしてこれからも精進し、より高い技術力を身につけていきたいです。
登壇した方向けに、タイミーさんからコースターを貰いました。大切に使います🍹
会場で分からなかったことに関して、管理者の堀井 雄太さん(@yutadayo)やhiroteaさん(@nifuchi222222)が丁寧に教えてくださって、とても助かりました。🙏
改めて、発表を聞いてくださった皆様、ありがとうございました!
発表スライドがはてなブックマークの人気エントリーに掲載されていました。ブックマークしてくださった皆様、ありがとうございます!!
(t_wadaさんの記事の隣で嬉しいです🦁)