White Box技術部

WEB開発のあれこれ(と何か)

最近サービス作るときに考えていること

この頃、新しくサービスを作ることが多かった&続いているので、どんな事を考えて作っていたかを思い出しながら書いてみます。

最初にざっくり考えること

  1. どういったデータを扱うか
    1. 認証が必要なアプリケーションか
      1. 面倒くさいからできればやりたくない・・・
    2. ドメインごとのデータにどんなものがありそうか
      1. リアルタイム反映が必要なものはできればやりたくない・・・
    3. 画像や動画のこと
      1. お金がかかるからできればやりたくない・・・
  2. データはどうアクセスされるか
    1. アクセス頻度はどのくらいになりそうか
    2. バッチ処理が必要か
  3. DBどうするか
  4. 管理画面が必要か(大体いる
  5. 運用したときのコスト感

大体やりたくないので、やらなくていいこと探しているような気がします。

一通り構成を考えたら次はアプリケーションとインフラについて考えます。

  1. サービス実現をどうやるか
    1. トレンドの技術で、今回使えるのがないか
  2. 何か今までの作り方から変えれるところがないか
    1. 前回で改善したかったことが今回のでやれないか
  3. 新しいことの割合が多すぎないか
    1. どでかい挑戦を3つ以上入れない
    2. できれば1つ、無理して2つ
    3. 新しい言語の場合は、他を可能な限り既知の技術で収める

ここで大体やりたいことが増えます。なので最初に減らしているのかもですね!(面倒くさいだけ

アプリケーションをどうするか

方針が大体定まったらアプリケーションのリポジトリを作りながらアプリケーション構成を考えます。

  • とりあえずフルNext.js
    • フロントもバックエンドもTypescriptで作りたい
    • バックエンドがNext.jsで無理そうな場合はGoかRustかPythonあたり使う
      • Nestだと同じTSでもNextと結構方向性が違うから、別言語使うのと脳コストがあまりかわらない
  • DB管理はprisma使えるならprisma
    • Mongoならprismaじゃなくてmongoose
  • リポジトリはモノレポにする
    • yarn workspaceで管理する
      • そういう意味でもなるべくTypescript以外使いたくない
    • ルート直下にVSCodeワークスペース管理ファイルを置く
  • renovateを最初から入れない
    • ncuで都度チェックするからメンテナンスフェーズに入るまでいらない

インフラ構成をどうするか

  1. 要件満たせる上で一番コストがかからないサービスはどれか
    1. 最近よく脳内候補にあげるやつの順番は以下
      1. Vercel(この場合データはSupabase + Upstash か AWS
      2. GC(Cloud Runベース
      3. AWS(ECSベース
    2. 結局、慣れたAWSになりがち
  2. 無料枠はどのくらいあるのか
  3. 月の使用料金がどのくらいになるか

AWSの場合

  • リージョンはもうバージニア北部でいい
  • サービスが跳ねるまではVPCも1つでいい(ステージングを本番のに間借りさせる
    • そうすればLBも共有できるのでコストが抑えられる

インフラも構成の管理をどうするかとか色々考えているはずなんですけど、結局コストのことばっかり記憶に残ってますね、これは。

とりあえずここらへんまで考えてから、コードを書き始めている感じです。

あとがき

大体このくらい書いて1時間でした。 もっとコスト低くブログにアウトプットできないかと思い、1時間集中して書けるだけ書くをやってみた感じです。

1時間だと補足的なことが書けなかったので、それは別記事に回していこうと思います。

今回の記事を少しだけ補足すると、とりあえず生みたいになっているNext.jsの扱いですが、 Next.js以外(Svelteとか)もやってみたい気持ちはありつつも、Next.js自体が毎回新しいことやってくるので、 Nextの新しいことをやっていると他はまあいっかなってなっている感じです。

React Hook Formで複数項目間のバリデーション(相関チェック)

相関チェックって言葉、そういえばもう全然聞かないなーとは思いつつ、
React Hook Formで、複数項目をまたぐ入力値のチェックを実装したので知見を残しておきます。

↓こういうやつ

手順

ここでは郵便番号のように情報としては1つのものを、複数の入力項目で入力する場合を例にします。 また、手順は相関チェックをする場合に注意する箇所に絞って記載しています。

1. Formの型定義

分割した項目に対応した型(Zipcode)を定義し、それをReact Hook Formで扱うForm項目の型に設定します。

type Zipcode = {
  zip1: string;
  zip2: string;
};

type SampleForm = {
  zipcode: Zipcode;
}

2. バリデーションを設定

バリデーションはregisterのvalidateを使って記述します。 合わせて、チェック対応項目それぞれの変化をバリデーション結果に反映させるために、depsも利用する必要があります。

const validCondition = 
  {
    validate: {
      validateNumber: (_: number, formValues: SampleForm) => {
        const isValid1 = /^[0-9]{3}$/.test(formValues.zipcode.zip1);
        const isValid2 = /^[0-9]{4}$/.test(formValues.zipcode.zip2);
        return (isValid1 && isValid2) || "正しい郵便番号を入力してください";
      },
    },
    deps: ["zipcode.zip1", "zipcode.zip2"],
  };

今回の場合、バリデーションは同じ条件をzip1とzip2の両項目で使うことになります。

3. エラーメッセージを共通化

入力フィールド自体は複数あるので、zipcode.zip1とzipcode.zip2はそれぞれがエラーメッセージを持ちます。 とはいえ、この場合どちらも同じメッセージなので、以下のようにまとめます。

const errorMessage = errors?.zipcode?.zip1?.message || errors?.zipcode?.zip2?.message;

エラーメッセージ以外にも、項目のCSS表現を統一するためには、isDirtyのような状態も共有する必要があります。

4. Formの組み立て

あとは通常と同じようにReact Hook Formを利用してFormを組み立てれば、チェックが行われます。

以下はサンプルです。 InputTextFieldなどはこの記事で触れていない独自コンポーネントですが、概ねinputタグのようなものです。 あと、CSS情報も除いています。

<div>
  <label>
    {label}
    {required && (
      <div>
        <span style={{ marginLeft: "2px", color: "#dc3545" }}> *</span>
      </div>
    )}
  </label>
  <div>
    <div>
      <InputTextField
        type="tel"
        placeholder={"000"}
        required={required}
        invalid={errorMessage ? true : false}
        valid={isDirty}
        {...register(`zipcode.zip1`, validCondition)}
      />
    </div>
    <div>-</div>
    <div>
      <InputTextField
        type="tel"
        placeholder={"0000"}
        required={required}
        invalid={errorMessage ? true : false}
        valid={isDirty}
        {...register(`zipcode.zip2`, validCondition)}
      />
    </div>
  </div>
  <FormFeedback>{errorMessage}</FormFeedback>
</div>

おまけ

↑で触れてなかったInputTextFieldですが、普通のコンポーネントだとregisterを使ったときにrefに関するエラーが出るので、forwardRefを使って対策しています。

import classnames from "classnames/bind";
import { forwardRef } from "react";
import styles from "./index.module.scss";

const cx = classnames.bind(styles);

type Props = React.ComponentPropsWithoutRef<"input"> & {
  valid?: boolean;
  invalid?: boolean;
};

export const InputTextField = forwardRef<HTMLInputElement, Props>(
  (props, ref) => {
    const { valid, invalid, ...rest } = props;
    return (
      <input
        className={cx("input", props.className, {
          readonly: props.disabled || props.readOnly,
          valid: valid,
          invalid: invalid,
        })}
        {...rest}
        ref={ref}
      />
    );
  }
);
InputTextField.displayName = "InputTextField";

参考

【C100対応サークルチェッカー】Circle Checker2を作りました

以前にも紹介した、Twitterのユーザ名からイベント参加情報を抽出するツール「Circle Checker」ですが、ややあってRustで作り直しました。

以前の記事はこちらです

なので今回は新しく作ったCircle Checker2の使い方と、前バージョンとの違い、QAなどを書いていこうと思います。

続きを読む

マザボが壊れたのでWindows8.1からWindows10に乗り換えた(その後Win11になりました

これはWindows PCのマザーボード変更日記です。

だいぶ記事を寝かしてしまったので、今が2022年1月の気分で読んで下さい

「何もしてないのに壊れた」

年が明けてから、毎朝液タブでのクロッキーを習慣にしているのですが、ある日、電源ボタンを押してもBIOSが起動しない自体が発生しました。

この日は「あ、マザボリチウム電池が切れたな」と人生二度目のマザーボード電池交換をすることで復旧させることができたのですが、 明けて次の日、二度とBIOSが起動してくることはありませんでした。。。

2013年に組んだので、寿命は9年でした。

実は

そろそろWin8.1じゃ駄目だろうと、Win10を入れた起動ドライブを作ったり、大枚叩いてM1MAXなMacを買ったりしていたのですが、 肝心の絵を描く環境の移行を全然していなかったのです。

Win10環境作ったら、「お前のPC、Win11駄目だから!」ってMSに言われたり、 「Macへのクリスタ設定の引き継ぎ、よくわからん」ってなったせいなのですが。

思い返せば初代自作PCマザーボードの電池交換のあと、HDDがぶっとんで使えなくなったので、 マザーボード付属のリチウム電池が切れた場合は、新しいPCの準備を始めるのが良いのかもしれません。

「とりあえず、マザボだけ買うか」

というわけにはもちろんいかず、CPUとメモリは最低限買い替える必要があります。会社辞めるというのにこの出費よ。。。

気を取り直して、マザーボード選びからしました。
使っていたマザーボードASUSのだったので、今回もASUSから探していったのですが、いいなと思ったProArt B660-CREATOR D4はまだ出てなかったので、

「じゃあなんかそれなりのでいいか」

とこれらをツクモで買ってきたわけです。

それなりとか言いながら、ちょっとだけ奮発しました

2.5インチSSDじゃ駄目だった

後はWin10のOS入っているSSD繋いでおしまいかと思っていたのですが、最新のマザーボードは起動ディスクとしてSATAスロットのディスクを認識しませんでした。。。

いろいろ調べていると、新し目のマザーボードはM2スロットだけが起動ディスクになるようで、SATAのディスクでも起動するにはCMS機能を有効にする必要があるようでした。

この機能を有効にするには、グラフィックボードがマザーボードに挿されてなければならず、そうするとCPUについているグラフィック機能は使えなくなり、 intelのF無し型番を買った意味は消失しました・・・

ともあれしょうがないので、前のマザーボードにも挿していたグラフィックボードをはめ込み、CMSを有効にしました。

新しいマザーボードで過去環境を起動するのは難しい

とりあえず前も使っていたWin8.1のOSで起動し、クリスタ環境を移行しようとしたのですが、 そもそもマザーボードWindows 8.1に対応していないようで、ドライバの類がインストールできず、Win8.1環境ではネットに繋ぐことができなくなってしまいました。

まあそれも致し方なしかと思い、設定のコピー作業を数分していたところ、CPUが100%で張り付きました。 タスクマネージャで見る限り、特に何かがパワーを食っているようでもなかったので、とりあえず一旦PCを終了させ、再度立ち上げましたが、 2分くらいするとやはり100%になるようだったので、これも旧OSとマザーボードとの相性問題なのかもしれません。

更にいうと今回買った今のマザーボードSATAが4ポートで、他がM2とかいう固定するタイプのスロットになってたので、 過去環境と同じにするにはSATAポートが足りませんでした。

なので過去環境をそのまま移行するような場合は、最新のマザーボードを選んでもあまり利点はないのかもしれないですね。

大人しく全部買い換えましょう!

クリスタ環境の移行

公式の説明どおりに実行すれば移行はできました。

ただキャンバス設定は移行されなかったので、CPUが張り付く前に画面キャプチャを撮っておき、手動で設定し直しました。

XP-PENの液晶タブレット移行で詰まったところ

前の環境だとできなかった4K表示ができたので嬉しかったのですが、描画遅延が発生していました。
色々見てみたのですが、Win10だとディスプレイのリフレッシュレートも変更できるようで、そこが30Hzになっていました。

これは60Hz近くが設定できるまで解像度を落とすことで解消できました。

その後の話

数日使っていると、Windows11のアップデートが配信されたので、面倒くさいことは早めに済ましたい思いから、そのままアップデートを実行しました。

新しいOSなので不具合出るかなとは思ったのですが、意外と問題なく環境が引き継がれていました。

ともあれWindows11に全く問題がないわけでもなく、Windows Updateのあとにサウンド設定が初期化されてしまったり、画面設定がおかしくなったりはします。 設定し直せば元に戻すことはできるので、苦汁をなめさせられてきたWindows Update問題の中ではマシな方だとは思います。

それでもWindows11は今までのWindowsで一番しっくり来ている感じなので、アップデートおすすめです。