10GbEのついたあやしいミニPCのR86Sを買って、eMMCにProxmoxを入れてみた

はじめましての人ははじめまして。そうでないひとはお久しぶりです。猫ロキP(@deflis/id:deflis55)です。

昨年末に光クロスを導入したので10GbE環境になりました。(ちなみにenひかりクロスでWXR-6000AX12Sを格安で売ってもらっているので実はあまり困っていませんでしたが) というわけで、せっかく10GbE環境を手に入れたので、以前から興味のあったProxmox VE環境を整えたいという意味も込めて10GbE NICが内蔵されたR86Sをポチってみました。

ちなみにAliexpressで買いました。そっちだと9.5万が7万弱なのでアリエクで買うことをオススメします。届くまでおおよそ2週間ぐらいかかりました。 あ、N6005/32GBのモデルを買ったんですがN100/16GBのモデルも同じぐらいの値段で出ていたので、そちらを探す方がきっと幸せになれると思います。 (N100のほうにはまだ32GBモデルはないようです。不幸中の幸い。)

Proxmox VEのインストールは拍子抜けするぐらい簡単にできました。 一つだけ問題があるとするとeMMCをインストール先に選ぶと、インストーラーがエラー落ちするところでしょうか。

続きを読む

Next.jsのApp Directory/App RouteとFirebase Authenticationをいい感じに統合するソリューションはまだない。

ほかにこの罠にはまる人がいなくなるための備忘録です。

いくら探しても表題通りのソリューションは見つかりませんでした。 そもそも、SSG/ISR/SSRと認証はかなり相性が悪そうなので、諦めてほかのソリューション(Viteとか)をつかうべきなのでしょう。

なにかいいソリューションがあるなら教えてください。それでは…。

Next.jsのapp routeつかってみて、時代の移り変わりを感じた

はじめましての人ははじめまして。そうでないひとはお久しぶりです。猫ロキP(@deflis/id:deflis55)です。

最近個人開発でNext.jsのapp routeをつかってみたのでその感想を書きたいと思います。 つれづれないままなので、まとまってなかったらすみません。

App Routerとは

Next.jsにおける、新しいアーキテクチャのルーティングです。 特徴としては、基本的な処理がServer Componentになり、ほとんどがSSG/ISRになるところでしょうか。

useStateなども使えないので、基本的にはpropsを受け取るか、fetchなどでデータを取得することになります。 fetchされるものも基本的に静的になるので、静的サイトジェネレーターとしての機能が強くなったイメージです。

なぜApp Routerを使ったのか

単純に、Next.jsの新しい機能を使ってみたかったからです。

また、(ここではリンクを張りませんが)作ったものはYouTubeやブログの更新情報を含んだポートフォリオなので、ほぼ静的サイトだけどもたまに更新されるという性質だったので、App Routerに向いていたからです。

というのは後付けの理由で、やってみたらそういうポートフォリオであればかなりApp Routerの特徴を活かせるなと思いました。クライアント側で動的に要素を変える必要がほとんどなければかなりいい選択肢になると思います。

使ってみてよかったところ

よかったところとしては、コンポーネントに直接fetchを書くと自動でISRされるところです。 今までReactQueryとかで苦労して取得していたりしたのでそういうのがスッキリ書けるようになった気がします。ずっといろんな難しい感じでデータ取得処理を書いていた感じがするので、これでだいぶ楽になるかなぁと思いました。

fetchの引数に revalidate を書くだけで、ISRの間隔を設定できるようになったのも革命的だと思いました。 これによって、既存のノウハウをそのまま活かしてISRを書くことができて非常に便利でした。感覚的にはSSRで書いているのと同じ感じで開発できました。

使ってみてよくなかったところ

よくなかったところとしては、クライアント側にコンポーネントを移さないと以前のノウハウやコンポーネントが利用できなくなっているところです。クライアントサイドで処理をするように"use client";を書けばいいんですが、そういうことを書くと頭の中でコンテキストスイッチが走るので難しいなと思ったりしています。

あと既存のコンポーネントをそのままServer Componentとして使えなくなっていそうな感じがしています。例えば、Material-UIとかを使おうとするとクライアントコードが増えて大変だろうなと思います。ただ、Next.jsとその手のコンポーネントの相性は年々悪くなっていっている印象があります。 Next.js的にはCSSモジュールやTailwind CSSを使ってほしいというのは見えていて、そういうCSSを直接各時代に戻ればそこまで問題ではなさそうとは思いますが…。

今回の場合は移行元のサイトがCSSフレームワークのBulmaを使っていたので、デザインそのままで移植しました。今回はこれで乗り切りましたが、Material UIとかEmotionを使っていたらもっと移行が大変だっただろうなと思っています…。

ディレクトリの切り方の工夫とかも必要そうで、atomic designの上になにかもう一つレイヤーがいりそうだなとかそういう事を考えています。 今回はあまりコンポーネントが多くなかったので適当に /components にServer Componentを置いて /components/client にClient Componentを置くことにしました。 なんかいい感じの切り方が他にあるなら教えてほしいです。

また、今回はつかってないんですが、Server Actionsを使ったフォームとかの処理に面食らう人も多そうな印象です。良くも悪くもPHP的な感じが否めず、まだ粗削りで変なところにバグを仕込んでしまいそうな感じがしています。そのうちこれをベースに、React-hook-formみたいないい感じのライブラリが出てきてくれることを祈っています。

まとめ

ポートフォリオみたいな半静的サイトを作るようなときの選択肢としてはApp Routerがかなり良いと思います。 XMLパーサなどのNode.jsの資産はだいたい使える感じですし、ISRもわかりやすくなりました。 ちょっとしたCSRを含む程度ならページのレンダリングは爆速です。

一方、まだベータですがServer Actionsはまだまだこれからという感じを受けました。そもそも新しいパラダイムで周辺環境が整っていないのもありますが、使い方に注意が必要でまだ実運用で使うときには大変だろうなと思いました。しかし、良くも悪くもまだ出たばかりの機能なので、今後どのようにエコシステムが発展していくのかが気になっています。これらのデメリットはエコシステムが広がれば問題なくなるところだと思っています。

色々文句は書いていますが、その手間に見合うメリットはかなりあると思っているので今後も使っていきたいと思います。 さすが業界最大手のNext.jsという感じでした。Gatsby潰しだ…!

TypeScript 4.9から導入された satisfies 演算子で安全に配列やオブジェクトを作ろう

はじめましての人ははじめまして。そうでないひとはお久しぶりです。猫ロキ P(@deflis/id:deflis55)です。

TypeScript 4.9 で導入された新しい演算子 satisfies をご存知でしょうか? 自分には関係ないと思っている人も多いと思うんですが、意外と使えるところが多いので、ここで紹介したいと思います。

satisfies 演算子とは?

簡単に解説します。詳しくはリリースノートを見てください。 www.typescriptlang.org

TypeScript では as const という const アサーションによって静的なオブジェクトを作ることができます。

type ColorName = 'prop1' | 'prop2';

const obj: Record<ColorName, string> = {
  prop1: 'value1',
  prop2: 'value2',
} as const;

このように、as const をつけることで、オブジェクトのプロパティが readonly になり、型安全にできるのですが、一つ問題がありました。 この例だと問題ないのですが、もう少し発展した例を見てみましょう。

type ColorName = 'red' | 'green' | 'blue';

type Color = readonly [number, number, number] | string;

const obj: Record<ColorName, Color> = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [0, 0, 255],
} as const;

これで obj にアクセスしようとしたとき obj の中に入っている値の型が string | [number, number, number] になってしまいます。 これでは string か number の配列(タプル)か判断することができなくなります。

そこで satisfies 演算子が登場します。

type ColorName = 'red' | 'green' | 'blue';

type Color = readonly [number, number, number] | string;

const obj = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [0, 0, 255],
} as const satisfies Record<ColorName, Color>;

このようにすると green の値だけが string でほかがタプルになっていることが型推論により分かるようになります。

どこで使えるの?

特定の値だけ入っている配列を作りたい

as constsatisfies を組み合わせることで、特定の値だけ入っている配列を作ることができます。

type ColorName = 'red' | 'green' | 'blue';

const colors = ['red', 'green', 'blue'] as const satisfies readonly ColorName[];

// これだと型推論が効かない
const colors = ['red', 'green', 'blue'] as const;

// これだと型推論が効くが、長さが不定の配列になる。一部だけ抜き出したりするときには使えない。
const colors: readonly ColorName[] = ['red', 'green', 'blue'] as const;

このようにすると colors の中には 'red' | 'green' | 'blue' しか入っていないことが型推論により分かるようになります。いままでは ColorName が入っていることが保証できないか、タプルではなく不定帳として束縛されるようになります。

type ColorName = 'red' | 'green' | 'blue';

const allowedColor = ['red', 'green'] as const satisfies readonly ColorName[];
type AllowedColor = (typeof allowedColor)[number]; // 'red' | 'green'

こういうふうにすると、allowedColor に入っている値だけを使って型を作ることもできます。

OpenAPI Generator や GraphQL Code Generator で生成された型のうちどれかを使いたい、みたいなときに役に立つのではないでしょうか。もちろん、全部使いたいときもミスしてないか保証できるので便利です。

特定のキーのオブジェクトを作りたい

これはまさにさっきの satisfies 演算子とは? で紹介した例です。

type ColorName = 'red' | 'green' | 'blue';

type Color = readonly [number, number, number] | string;

const obj = {
  red: [255, 0, 0],
  green: '#00ff00',
  blue: [0, 0, 255],
} as const satisfies Record<ColorName, Color>;

これによって、objがColorNameのキーを持ち、その値がColorであることが型推論により分かるようになります。 こんな複雑でなくても、 Record<ColorName, string> のような簡単なものでも意識的に使っていくと良いと思います。

さっきの例と組み合わせるとこんな感じの使い方ができるでしょう。

type ColorName = 'red' | 'green' | 'blue';

const allowedColor = ['red', 'green'] as const satisfies readonly ColorName[];
type AllowedColor = (typeof allowedColor)[number]; // 'red' | 'green'

const allowedColorNotation = {
  red: '赤',
  green: '緑',
} as const satisfies Record<AllowedColor, string>;

まとめ

意外とこういうところで使えるっていうのを紹介した記事がなかったので書いてみました。 使い所は他にもあると思うので活用してみてください!

それではよきTypeScriptライフを!

○○の帽子を被るって表現が好き

はてなの社内用語というか自分の今いるチームだけかもしれないですが、最近社内で「エンジニアの帽子を被る」「マネージャーの帽子を被る」という表現をよく聞くようになりました。

人間誰しもポジショントークをすることがあると思うんですけど、自分の複数あるポジションでそれぞれ対立するトークをしたい時があると思います。 そんなときにこの「〇〇の帽子を被る」は便利です。

最初の例だと、エンジニア兼マネージャーみたいな人が「マネージャーの身としては嬉しいんだけど、エンジニアの身としては嬉しくない」っていうのを「マネージャーの帽子を被ったときは嬉しいけど、エンジニアの帽子を被ったときはうれしくない」と表現する感じです。

これ、他のことにも応用できると思っていて、ユーザー目線と開発者目線みたいなのが必要なときに役に立つと思うのです。

「ユーザーの帽子を被るとめっちゃほしいんだけど、開発者のl帽子を被るとめっちゃ面倒だからすぐはできない」みたいなことは往々にしてありがち。 でも、それぞれの帽子被って見える目線を戦わせれば、落とし所みたいなところが見つかると思うのです。 消費者の目線と作り手の目線ってどっちも大切なので、どちらも忘れないようにしていきたいものです。

まぁそんな感じで複数のポジションを表現する面白い方法を知ったので活用していきたいなって思ってる次第です。


【4/20 13:40追記】

あとでブコメとかで指摘されたんだけど、割と一般的な英語イディオムの wearing several hats をそのまま直訳で日本語で使っているということらしい。

これらの本で使われてる表現だそうです。

(結論はまだ出てない)ターミナルをいい感じにしたい話

ここ1年ぐらい*1から、ターミナル環境を良くしようという活動を頑張っている。

今使ってる環境が Windows / macOS / Manjaro Linux と、完全マルチプラットフォームな感じになっておりそれぞれで違うものをあんまり使いたくはない。 悩んでるけど結論が出ないので、ここに備忘録的にかいておこうと思う。

*1:だいたいchezmoi + oh-my-poshを導入したあたり

続きを読む