Rust + YewでTypeScript + Reactをリライトしてみた
あけましておめでとうございます。鏡開きギリギリなのでまだそう言っていいはず・・・。気付いたら転職して大体2年経過していたり、引越してから一年過ぎていたりして、時間の流れははえーなぁ、と思う日々です。 大体一ヶ月くらいセコセコとやって、年末年始も(珍しく)実家で作業していたりしたやつが、基本部分は動くようになったので、それについて書いてみます。 ...
あけましておめでとうございます。鏡開きギリギリなのでまだそう言っていいはず・・・。気付いたら転職して大体2年経過していたり、引越してから一年過ぎていたりして、時間の流れははえーなぁ、と思う日々です。 大体一ヶ月くらいセコセコとやって、年末年始も(珍しく)実家で作業していたりしたやつが、基本部分は動くようになったので、それについて書いてみます。 ...
あけましておめでとうございます。鏡開きギリギリなのでまだそう言っていいはず・・・。気付いたら転職して大体2年経過していたり、引越してから一年過ぎていたりして、時間の流れははえーなぁ、と思う日々です。 大体一ヶ月くらいセコセコとやって、年末年始も(珍しく)実家で作業していたりしたやつが、基本部分は動くようになったので、それについて書いてみます。 <!–more–> きっかけ きっかけは単純で、色々見ていたときに、 yew というフレームワークを見つけたから、です。 https://yew.rs/ どういうものかというと、 Rust製 React.jsを強く指向したコンポーネントライブラリ 周辺にstate管理(だけじゃないけど後述)、ルーターなども整備していて、必要最小限は揃っている というものです。超荒く言うと、 Rustで全部やっちゃおうぜ というやつですね。js_of_ocamlとかBucklescriptとかで実際似たようなことをやっていた身としては馴染があります。あっていいのか。結論的には、いつもの やってみたかった駆動開発 です。 リポジトリ https://github.com/derui/simple-planning-poker/tree/yew すでにこのリポジトリが盛大な実験場となっているのは気にしないでください この記事の時点だと、必要最小限成立する程度の機能までしかできてません。一応道筋は見えているので、実装自体は簡単ではありますが。 構成 利用しているライブラリはCargo.tomlを見たらだいたいわかるようになっていますが、それ以外の構成も含めて、利用しているツールなど。 Rustは最新安定版 yarn v3 ずーっとv1使ってきましたが、アップグレードしてみました Webpack 5 wasm-pack + wasm-pack-plugin メインのprojectとサブprojectとして分離 ルートのCargo.tomlには、projectsの定義のみ入れています ライトなCleanArchitecture的思想 ただし、これはプロジェクト構成を失敗した感も・・・ yew-agent/yew-routerを利用してルーティングとか wasm-bindgen + gloo + wasm-bindgen-future Firebase(realtime database/auth)を利用 当然Rustから呼んでます TSな部分は、依存をglobalに展開 + Firebaseの初期化のみ という形になっています。ぶっちゃけ途中はテストも書かずにひたすら移植作業していたので、実際に動くのかどうか?は実際に動かしながら試してみた・・・というあんまりよくない形になっています。が、テスト書きながらだと多分この2倍かかった気がするので、とりあえずどういうものなのか?を確かめるという目的を達成するためにはこれでよかったかな、と。 yewでどうやって書くのか? Rustがどういうものか、とかは全部すっとばします。Rust公式に良質なドキュメントがあるのでそちらをどうぞ。また、初期セットアップも全部すっとばします。公式ドキュメントを見たほうが早いです。 超簡単なサンプルとしてはこんな感じになります。 #[derive(Properties, PartialEq)] pub struct Property { counter: u32, } #[function_component(Component)] pub fn component(props: &Property) -> Html { html! { <div><span> {"Counter: "} </span><span> {props.counter}</span></div> } } #[function_component(Main)] pub fn main() -> Html { let state = use_state(|| 0); let onclick = { let state = state.clone(); Callback::from(|_| state.set(*state + 1)) }; html! { <Component counter={*state} /> <button onclick={onclick}>{"Click"}</button> } } yewは、 struct component と functional component という二通りの実装が可能です。この辺もReactのClass ComponentとFunctional Componentとよく相似していますね。 ...
今年も終わりですね。なんだかんだ色々ありましたが、個人的には総じて悪くない年だったんだじゃないかと思ってます。 多分今年最後の記事ですが、ネタが無いので小ネタでお茶を濁そうかと・・・。 <!–more–> Emacs29での結構重要な変更 私は現在、 native comp + pgtkを利用したい、という理由でEmacsのmasterを適宜ビルドして利用しているのですが、29の開発フェーズに入ってからビルドしなおしたら、なんか画面に違和感を覚えました。 さて、左側がアクティブなバッファ、右側が非アクティブなバッファです。何が違うでしょうか?まぁ見たまんまですが、mode lineのフォントが明らかに異なります。 私は現在フォントとしてはHackGenを愛用しているので、等幅フォントとなっています これは、Emacs 29において、mode lineをプロポーショナルフォントを利用する、という決定が入ったためらしいです。 https://lars.ingebrigtsen.no/2021/11/24/the-most-controversial-change-in-emacs-history/ ↑の記事によると、かつてあったXEmacsでmode lineにプロポーショナルフォントを導入していたらしく(私もその時代はLinuxメインではない)、それがGNU Emacsにも導入されたことによる、ということのようです。 しかし私は等幅でありたい そもそもプロポーショナルフォントを用意していないので、見た目もよくないしガタガタするし、なので、この設定をさくっと無効化します。 Emacs 29から、mode lineのfaceとして、 mode-line-active というものが追加されています。これが、アクティブな場合のmode lineに対する設定となっています。 これのフォント設定がプロポーショナルなものを利用する、ということになっているので、要はこいつを元々のものに戻してやればいいです。 (leaf *mode-line-face :if (version<= "29" emacs-version) :config ;; mode lineをvariable pitchではなく等幅フォントを利用する。 (set-face-attribute 'mode-line-active nil :inherit 'mode-line)) プロポーショナルじゃなくてvariable pitchとなっていますが、まぁ実用上はどっちでも一緒です、きっと。 私はleafを利用している & Emacs 28とかでも利用するケースがあるので、バージョン指定を入れてますが、masterしか使わん!という人はバージョン指定を抜いてもよいかと。 masterならではの問題 とりあえずは対処できましたが、こういった(影響のある人にとっては)ドラスティックな変更が入ってくるのも、masterを利用する醍醐味?かな、と思う一時でした。調査と修正自体は10分ちょっとでできたんですが、最初は違和感がある・・・けどなんだ?という感じでしたので。 こういうのがあるとmasterは・・・ってありがちですが、でもnative comp + pgtkはとても快適なので、Wayland環境で生活されている人は是非一度試してみることをお勧めします。 fcitxとかでの入力がうまくできない?らしいので、SKKなりmozcを利用する必要がありますが。 それではよい年末年始をお過ごしください。
気がついたら12月が1/3過ぎていました。ちょっと時間の流れが歪んでいるレベルですね。 最近Rustを書く機会が増えてきたので、ちょっと整理しました。ネタが無いので小ネタです。 <!–more–> Emacsでの設定 私はRustもOCamlと同じくEmacsで開発するので、当然ながら設定もEmacsになります。 現状はrusticを利用していないので、rust-modeとその他で以下のような感じになってます。 (leaf rust-mode :straight t :custom (rust-indent-offset . 4) (rust-format-on-save . t) ;; formatの度にbufferが分割するのを避ける (rust-format-show-buffer . nil) :hook (rust-mode-hook . lsp) (rust-mode-hool . cargo-minor-mode)) (leaf cargo :straight t) (leaf *rust-analyzer :after f :if (and my:cargo-path my:rust-analyzer-version) :init (let* ((cargo-path (expand-file-name "bin" my:cargo-path)) (server-program (expand-file-name "rust-analyzer" cargo-path))) (unless (f-exists-p server-program) (let* ((target (cond ((eq window-system 'ns) "apple-darwin") (t "unknown-linux-gnu"))) (path (format "https://github.com/rust-analyzer/rust-analyzer/releases/download/%s/rust-analyzer-x86_64-%s.gz" my:rust-analyzer-version target))) (call-process "curl" nil nil t "-L" path "-o" "/tmp/rust-analyzer.gz") (call-process "gunzip" nil nil t "/tmp/rust-analyzer.gz") (f-move "/tmp/rust-analyzer" server-program) (message "Success rust-analyzer installation!"))))) 最後のrust-analyzerについては、後述する lsp-modeで利用するためです。rust-analyzerはnightlyじゃないとインストールできないのと、現在はmanualの方が推奨っぽいので。 ...
なんか休み以外にブログを書くということができなくなってきました。日記というわけでもないからまーいいんですけど。 今日はいつもと趣向を変えて、勤労感謝の日ということで、最近(といっても一ヶ月くらい前だけど)クリアしたゲームについて書こうかと思います。 <!–more–> Factorioの系譜(だと思う) Factorioというゲームをご存知でしょうか。知る人ぞ知る・・・というほど無名なわけでもない著名なゲームです。コンシューマやスマホゲーしかやらない、という方は聞いたことがあるかも?という程度だと思います。 すごい簡単に言うと、Factorioは 工場を作るゲーム です。バトルとかも色々ありますけど、とにかくコンベアとインサーターとよばれるロボットアームをひたすらに設置しまくっていくというゲームでもあります(語弊がある)。 さて、このFactorio、Steamなどで購入できますが、とにかく評価が高いです。少なくとも私が把握した4、5年前から、 圧倒的に高評価 という評価以外になったのを見たことがありません。このような高評価ゲームは、クローンなり同様のコンセプトを持ったゲームが生まれるのは歴史的にも必然でありますので、色々出ました。 Dyson Sphere Programはこのようなクローンの一つ(と私は認識している)ですが、その中でも特に成功しているものの一つです。 どういうゲーム? https://store.steampowered.com/app/1366540/Dyson_Sphere_Program ある目的のために、 惑星ごと工場にしていくゲーム です。 ゲームのサイクルとしては、 素材を採掘する 素材を加工する 加工した素材を利用して研究する をひたすらに繰り返します。 とにかくスケールが大きく、惑星・星系・星団と、ゲームが進むにつれてアクセスできる範囲が広がっていきます。距離とかがわりとリアルで、xxAUとか書いてあるとその通りの時間がかかるので、隣りの1光年先まで・・・とか考えてると死ぬほど時間がかかったりします。 タイトルにもありますが、ゲーム中でダイソンスフィアを作成することになります(作成しないとそもそもクリアできません)。このダイソンスフィアが目玉になります。 ダイソンスフィアのデザイン ゲーム中で作成するダイソンスフィアは、自由度はある程度制限されるものの、自分で自由にデザインすることができます。 ダイソンリングと呼ばれる構造体(ゲーム内ではソーラーセイルをストックする領域) ダイソン殻の構成 セイルと呼ばれます もちろん、デザインしても素材を与えるのと、ロケットの打ち上げとかをしないと、全くできていきません。そこらへんは当然自分でやるしかありません。しかし、自分でデザインしたダイソンスフィアが徐々に出来ていく様を見ているのはかなり楽しいです。 ただし、初期だと主星の赤道付近にしかセイルを設置できません。主星全体を包むような構造を作成したい場合は、かなりの時間がかかることを覚悟した方がよいです 星間移動 書いた通り、スケールがx光年という単位になっていきます。ちなみに、通常の移動速度は最大で2000km/sです(すさまじい速度ではありますが、宇宙空間だと遅すぎます)ので、当然ですがこのまま移動することはちょっと不可能です。 ではどうするのかというと、ゲームの進行に合わせて ワープ ができるようになります。これを利用して、複数の星系工場を広げて、他の星系で作成・採掘した素材をメインの星に送って・・・とかできるようになります。 が、このワープするためにはアイテムが必要で、当たり前ですが一回ワープするたびに一つ消費します。また、星間連絡船的なものを運用することもできますが、こいつらは往復で2つ消費します。 つまり、星間で様々な素材を融通しあおうとすると、このワープ素材の安定供給も必要になります。 Factorioとの違い Factorioも最近やりはじめたので、感じた違いを挙げておきます。 ただし、DSPでは現在バトルシステムがありません。多分これが完成したらEAが終わる、という感じかと。 一部の設備が3次元的に積み重ねられる Factorioは2D、DSPは3Dなので、一部の設備(研究所とチェストなど)は3次元的に積み重ねることができます Factorioでは積み重ねるという概念はないです また、コンベアも3次元的に構成できるので、ジェットコースターみたいなやつもやろうと思えばできます 設備を建築する場所が3次元的 Factorioは2Dなので、場所の制約や並べる制約というのは基本的にありません が、DSPでは建築する場所が星 = 球体なので、例えば北極や南極といった極域では、建設にできる方向にかなりの制約がかかります スペース自体も変化するため、経度に沿って並べると後で後悔することがまれによくあります 自分の手で建築できない DSPでは、すべての建築は建築ドローン(消費しない)がおこないます 逆にいうと、それ以外では行えないので、コンベアを引いたりするときにあんまり長い距離を引こうとすると、常にエネルギーがない状態になって動けなくなったりします(実体験) 自分自身にエネルギーがある 自分のエネルギーを利用して、手作業での工作や建築というのを行うため、自分自身に燃料を入れつづける必要があります その代わり、工作装置とかは全部電力だけで動くので、リソース管理はやりやすいです コンベアは一列しかありません Factorioだと二列あるので、こっちとこっちから・・・とか合流して・・・とか考える必要があります DSPだと大分シンプルになります 後半になると星間物流船を使わないとやってられない 他の星にしかない素材(かつ必須)なものがあるので、絶対に必要になるのはそうなんですが、後半になればなるほどドローンがものを言います 逆に電車とかは存在しません 素材がシンプル Factorioだと硫黄とかそういうものを石油から分留して・・・みたいなのも必要ですが、こっちは大分シンプルです 他の星系とかも考えないといけないので、あまり多すぎると管理しきれない、というのもありそうですが などなど。大きな違いとしてはバトルシステムが無いというのと、3次元と2次元という次元の違い、というものかなと。 ...
今日は文化の日ですね。明治天皇の誕生日だそうです(調べた)。現在の上皇様の誕生日については平日になったりしてますが、日本はすでに祝日がめっちゃ多い国なので、これ以上増えてもなぁ、という。 そんなことはさておき、文化の日らしく?久し振りに新しいキーボードを作成しました。 <!–more–> 作ったやつ タイトルにもうがっつり書いていますが、claw44というキーボードになります。 公式から引用すると、特徴は 手を置いた時に自然な状態に落ち着くこと指の移動をスムーズにすること小指に優しく、親指をもっと活用してあげること だそうです。また、↑のページにあるような専用のキーキャップが用意されていたり(これの質感は非常にgoodでした)と、かなり力が入っています。 作ったのはこんな感じになりました。 親指キーキャップだけ、公式のショップで売られているものにしました。結構いいお値段したもので・・・。 ちなみに前利用していたのは Corne Cherryになります。多分遊舎工房が開く前に組み立てたやつなので、3年とか前ですかね。 購入したもの https://shop.dailycraft.jp/products/claw44 このキーボードの作者自身が運営しているショップで購入しました。上記でPro Microとかダイオードとか一通り入っているので、スイッチとキーキャップ、ケーブルだけあればOKです。 https://shop.dailycraft.jp/products/3dkeycaps_claw44 また、専用のキーキャップを購入しました。親指分のキャップが不足していたのと、3Dプリンタで作成されたものがどういう感じなのか気になったので。 なお、スイッチは前のキーボードから剥して再利用しています。親指部分はCherry MXの赤軸、それ以外は銀軸です。 銀軸については https://mag.nioufuku.net/2020/07/26/gadget/00067-cherrymx-silver-switch/ などが参考になります。個人的にRealforceの30gを利用していたくらいなので、押下圧は軽い方が好みです 組み立て難易度 (一気に作ったので途中の写真が無い・・・) 今回キーボードを作成した理由は、前使っていた自作キーボードのハンダが一部クラックしてしまったため & しばらく同じものを使っていたので別のものも使ってみたかった、という感じですね。 特にさっさと構築したかったのと、久しく半田付けをしていないのとめんどくさい表面実装を避けたかったので、普通のダイオードを利用できるこれにしました。 遊舎工房とかで結構見ましたが、最近出たようなものは大半が薄さを意識してか表面実装ダイオードでした。部屋で利用するものなので、多少分厚くても全然問題ないかなーと思います ソケット部分が多少めんどくさいですが、ダイオードが簡単だったり、左右の区別があるので間違えづらいなど、組み立て難易度としてはかなり簡単な方だと思います。これよりも簡単というか簡略化されているものとしては、Corne Cherry Lightなどかなーとは思いますね。ソケットが無いので、キーを取り替えるのが超めんどくさいですが、そもそもキーってそんなに入れ替えるのか?という話もあるので。 RGBとかそういうのは個人的にまったく不要なので、このくらいシンプルなものが好みです。 ファームウェア 元々corneで色々弄っていたので、これをできるだけ再利用しました。というかどっちもquantumを利用していたりするのは変わらないので、結果としてはレイアウトのところだけ弄ったら動きました。 https://github.com/derui/qmk_firmware/blob/master/keyboards/claw44/keymaps/derui/keymap.c なお、せっかくある親指キーのうち一つには特に割り振っていません。理由としては、 そこまで不足を感じていない 親指をそこまで広げると結構負荷を感じる 利用頻度の低いキーで単独で押したいものがあんまりない というのがあります。まぁ、なんか必要があったら追加します。 使用感 元々Corneを利用していたのですが、それよりもかなりダイナミックに薬指と小指に落差が設けられています。 そのため、最初はいつものとおりに打とうとしてキーの無い位置を叩くこともありました。ある程度慣れた現状だと、逆に小指をあんまり動かさなくても p とか q とかにアクセスしやすいので、逆にそれだけ手なりを動かしていたんだなぁ、という感覚です。 ただ、落差があったり斜めになっていたりと、タイピング向けの構成になっているので、ゲームでWASDを使うような感じにすると、逆に利用しがたい・・・みたいな感じですね。ただ、プログラミングとかする分にはまったく問題ないです。 専用のキーキャップもいい感じで、ちょっとフルセットにしとけばよかったか・・・と思ってるくらいには質感がよろしいです。余裕があれば是非お勧めします。 まとめ 久し振りにキーボードを作成して、まずは半田付けのやりかたを再度練習したりしてましたが、総じて満足です。実際にキーボードの半田がクラックしているのを見た瞬間は、HHKBを使うか・・・とかも思いましたが、ちょっといまさら分割していないやつを利用する気力もなかったので・・・。 HHKB自体は、その耐久性を生かして万が一のためのキーボードとして残してあります。まれに失敗してしまったりするともうHHKBしか頼れないので。 年末とかにむけて工作キットのノリでチャレンジしてみるのはいかがでしょうか。工具を買うのはな・・・って場合は遊舎工房などで貸出サービスもやってたりするようなので、行ける方はそちらを利用したりしてもよいと思います。 この文章はClaw44で書かれています。
気付いたら10月も終わりです。もう今年も残りは二ヶ月ということで、月日の流れは本当に速い。 さて、先日登場したParcel2.0を個人のプロダクトで試してみたので、それについてライトに書いてみます。 <!–more–> Parcelとは まずparcelとはなにか・・・ということですが、こちらについては公式ページを見てもらうのが一番早いです。あえてまとめるとすると out of the boxで動作するbundler dev server/hot reloadingなどが組み込み済 CSS/XML/JSONなどのbundleも組み込み済 minificationやimage optimizationなども実現 Rustで構築されているため、マルチコア利用かつ高速 という特徴があります。特にRustで構築されているということと、後述するようにtype checkingを省いているため、特にTypeScriptのビルドおよびbundleは特筆すべき速度です。 parcelで動かすようにしてみる https://github.com/derui/simple-planning-poker 犠牲となるのはこのリポジトリになります。元の構成はWebpack5でゼロから構築したものになります。 個人開発では、create-react-appとかNext.jsとかはあんまり使いたくない派閥です https://github.com/derui/simple-planning-poker/tree/parcel で、parcel化したものがこれになります。 parcelは、各種ツール(組み込まれているものに限る)の設定ファイルは自動的に読み込んでくれるので、設定ファイル群はそのまま残っています。 具体的な手順は以下のようになりました。 yarn add -D parcel @parcel/transformer-typescript-tsc tsc postcss.config.jsとかのJavaScriptで記述されていた設定をJSONに移行 TypeScriptと、tsconfig.jsonでpathsを利用していた場合、path設定を書き換える package.jsonのsourceでルートになるファイルを設定する webpackの利用をやめる TypeScriptを利用している場合の注意点 TypeScriptを利用しているとき、importでめっちゃ ../ のような相対パス表記が出るのを防ぐため、 paths に以下のような設定をしている場合があると思います。 { ..., basePath: "./", paths: { "@/*": ["src/ts/*"] } } 実はこの挙動ですが、TypeScriptのオリジナルコンパイラにおける独自拡張であり、Parcelでは動作しません。 parcel2.0のドキュメントではこのあたりの記述が存在しており、基本的には↓のような記述にする必要があります。 { ..., basePath: ".", paths: { "~*": ["./*"] } } こうしないと、bundle時に超大量のエラーが出て涙することになります。 実際JSによる設定レスでいけたのか? 結果としては、若干書き換えは必要でしたが、 JSでの設定レス でビルドできることは確認しました。postcssとかeslintの設定に関しては、デフォルトの挙動で構わないのであれば、本当に設定レスで動かすことができるでしょう。 ...
仕事の方で、GraphQLをちょっと検討しだした + 個人的にも興味は持っていたので、本格的に触ってみることにしました。 GraphQLをKotlin + SpringBootで利用する方法としては、大きく三つありそうです。 graphql-java-kickstar Domain Graph Service Spring GraphQL の三つがありそうです。どれもコアとしてはgraphql-javaを利用しているため、どのように統合するか?が焦点になっていますね。 Spring GraphQLは、記事の時点(2021/10)では1.0にむけてのマイルストーンを粛々と実装している、という状態です 今回は、graphql-spring-boot-starterを利用してみた感想をば。なお、そもそもGraphQLとは?については、 公式サイトを見ましょう。 <!–more–> セットアップ さて、まずはセットアップ・・・なんですが、実はこのセットアップが大分苦戦しました。なぜかというと、2021/10時点で検索できる記事だと、結構古いパッケージ構造になっているケースが多く、色々動かない・・・というのがあったためです。 現状、 graphql-java-tools graphql-spring-boot-starter graphql-java-servlet といった関連は、すべて graphql-java-kickstart というGitHub Organizationにまとめられているので、こっちを使うのが第一になるかと。 plugins { id("org.springframework.boot") } apply(plugin = "io.spring.dependency-management") dependencies { implementation("org.springframework.boot:spring-boot-starter-web") implementation("com.graphql-java-kickstart:graphql-spring-boot-starter:12.0.0") implementation("com.graphql-java-kickstart:graphql-java-tools:12.0.0") } 最小構成だと↑のような感じになります。バージョンなどはよしなに。 schemaとのマッピング graphql-java-toolsを利用するかしないか、で大分書きかたが異なりますが、基本的にはgraphql-spring-boot-starterを利用する場合は併用しておいた方がよさそうです。 GitHubにも書いていますが、必要なら↓のようなpropertiesを追記します。 graphql: tools: schema-location-pattern: "**/*.graphqls" # Enable or disable the introspection query. Disabling it puts your server in contravention of the GraphQL # specification and expectations of most clients, so use this option with caution introspection-enabled: true さて、マッピングについてはgraphql-java-toolsに準ずるので、Queryに関しては結構シンプルに書くことができます。 ...
10月になっても半袖で十分というのはどうなんだ、と思いつつ、でもようやく涼しくなるようになってきました。 リモートワークでも生活でもずーっと使っているデスク環境を更新したので、その話を書こうかと思います。 <!–more–> 元々のデスク環境 さて、そもそも以前のデスクはどんな感じだったのかというと。 こんな感じでした.これは実際にデスク周りを変更する直前なのでディスプレイとかは電源切ってます。 このデスクのスペックとデスクの上にあったものとして、 デスク( 幅160cm x 奥行60cm x 高さ70cm ) ディスプレイ2枚 27inch デスクトップスピーカー キーボード トラックボール コントローラー2個 PS5 ちょっとした物いれ がありました。PS5は右のディスプレイの影になってますね。左端にちょこっと見えてる台みたいなやつは、デスクトップPCのキャリアです。 前の構成の課題 このデスクは前の部屋でも使っていたものを持ってきたやつですが、新しい部屋で使ううちに色々課題が生まれてきました。 左側のデッドスペースが気になる デスクトップを入れているキャリアは、その上部空間がまるごと無駄になってます ゲームのコントローラーをしまう場所が無い 別にいいんですが、いつまでも剥き出しというのも・・・ というかこのデスクは仕事でも使うので、これはこれでどうなん?という 上下のスペースが活用できていない デスクの幅が160cmあるので、特に右側とかは上部に隙間がないという感じになってます。 これらの課題をどうしようかな、と考えてみました。 デスクの幅が広すぎるので、もうちょっと狭くしても問題ない 逆に、奥行がもうちょっとあってもよいかな、という考えにもなりました iPadが置いてある辺に、通常はノートPCが置いてあるので、若干奥行が微妙だったりします 右にあるディスプレイをPC台の上に持っていく 地震があったりするとちょっと怖いですが、エルゴトロンを信じて サイドデスク的なもので上下のスペースを活用する PS5とかをデスクの上に載せないで、別に載せる感じで 後、デスクはまだリモートワークが続きそうでもある & 生活のほぼすべてがこの周辺なので、立ちながらとかできるように、電動昇降デスクを検討しました。 劇的After さて、とりあえず更新してみました。 ジャーン。ちなみにこれはまだ配置を調整している最中なので、現在はもうちょっと調整されてます。 更新ポイントは以下のような感じです。 憧れの電動昇降デスクにした サブデスクを導入した ディスプレイの配置を変更した スピーカーの位置を調整した 電動昇降デスクとサブデスクは↓にしました。サブデスクというかメタルラックなんですけど、ちょうどいいやつがこれくらいしかなかったんです。 デスクは、調べてみるとFlexiSpotを利用している・・・というのがかなり多かったので、最初はそれを検討してました。しかし、それらの記事をよく読むと、半分くらいが FlexiSpotから提供を受けている ということがわかりました。 これはマーケティングの一環として行われていることだとは思いますので、それ自体はよいのですが、実際それ以外のレビューを見ていると、サポートとかに課題がありそうだった & とてもいいお値段がするので、ちょっとどうしようかなぁ・・・、となってしまいました。 結局は、同等の機能があって一応国内メーカーである 山善 製のものを選択しました。 デスク全部合わせても椅子より安いんですけどね ちなみに電動昇降デスクは、大人二人で1時間〜1時間半くらいかかる、ということでしたが、実際に大人一人でやってみたところ、始めたのを若干後悔するくらい時間がかかりました。腰をやらなくてよかったです。 で、どうなの? まだ移行してから1日しか経過していませんが、左にあるマイクスタンドさえなんとかなれば・・・という感じです。現状ここ以外に置けないのですが、ここにあると左側のディスプレイがちょっと見えないんだけど・・・となってしまってます。 ...
もう9月も末で、涼しくなってきたなぁと思ったらいきなり暑くなったりと、季節があっちこっちいきますね。これも温暖化の影響でしょうか。 今回も小ネタで、最近やったfirebaseのrealtime databaseでローカルのテストをやる方法をサラッと書いてみます <!–more–> Realtime databaseをローカルで動かす Realtime databaseのテスト手法にはいくつかあると思いますが、基本的にはローカルで動作するemulatorを利用します。 https://firebase.google.com/docs/emulator-suite?authuser=0 β版とはいえ、かなりしっかりできている印象で、少なくともローカルでテストするレベルであれば必要十分です。さすがに実Databaseに比べると、レイテンシーがなさすぎて(そりゃそうだ)、実際にpublishして動かしたときに アレ? ってなる可能性もありますが。 さて、このemulatorですが、firebaseコマンドで初期化するときに選択しているか、configで追加したら、後は以下のコマンドを叩くだけで起動します。 $ npx firebase emulators:start デフォルトでは localhost:4000 で起動し、 localhost:9000 とかでrealtime databaseが起動します。この状態でも、databaseには繋げることができるので、やろうと思えばテストを書けます。 emulators:start の問題 しかし、emulators:startにはいくつか問題があります。 そのなかでも大きな問題は、 backgroundでの起動ができない & テストに同期して落とすとかできない という点です。まぁそりゃそうなんですが。 emulators:exec を使おう そんなときに役立つのが、 emulators:exec というコマンドです。このコマンドは、引数で渡されたコマンドを実行する前後でemulatorのstart/stopをきちんとやってくれる、one-pathなemulatorの起動を提供してくれます。 なので、 $ npx firebase emulators:start npm run test のように書けば、テストが開始する前にemulatorが立ち上がって、テストが終了するとemulatorが終了します。 また、引数に渡したコマンドがwatchとかであれば、watchを C-c とかで落とすまでずっと立ち上がりっぱなしになるので、ずっとテストしてられます。 realtime databaseを使うIntegration test こんな塩梅のボイラープレートを書く必要があります。RulesTestEnvironmentは、 @firebase/rules-unit-testing で提供されている便利ツールです。firebaseと結合したテストを書く場合はこれを使っておくのがよさげかと思います。 let database: any; let testEnv: RulesTestEnvironment; beforeAll(async () => { testEnv = await initializeTestEnvironment({ projectId: "demo-project-1234", database: { host: "localhost", port: 9000, }, }); database = testEnv.authenticatedContext("alice").database(); }); afterAll(async () => { testEnv.cleanup(); }); afterEach(async () => { await testEnv.clearDatabase(); }); 若干の課題 多分私の書いてるソースがどっかおかしいんだと思いますが、実行されるタイミングとか順番によっては、うまくデータが初期化されていなかったりなんだりします。これは原因を探っているところではありますが、基本的にはかなりの速度で動作してくれるので、ある程度の数のテストがあっても問題はなさそうです。 ...