UGA Boxxx

つぶやきの延長のつもりで、知ったこと思ったこと書いてます

【CSS】論理プロパティ

State of CSS 2022 を眺めていて知らなかったことのうち、論理プロパティについて調べた

CSSの論理プロパティ

CSSの論理プロパティとは従来の左上を開始位置にするのではなく、言語によってその開始位置などが切り替わるというもの

例えば、縦書きの日本語は右上から始まり左に文章が積まれていく

もし文章と文章の間にpaddingを設けたい場合、かつ、英語と縦書き日本語が何かしらで切り替えられる場合

padding-topとpadding-rightを文章に合わせて切り替えなければならない

これまでだと少し面倒だが、このCSSの論理プロパティを使うと文章の開始が自動的に切り替わってくれる

CSSの論理プロパティの一つpadding-block-startは文章が積み重なる側のpaddingを意味している

つまり、英語の場合、padding-block-startpadding-topと同じ

縦書きの日本語の場合、padding-block-startは、padding-rightと同じになる


padding-block-start - CSS: カスケーディングスタイルシート | MDN

他にプロパティがあり、今後多言語対応する場合は論理プロパティにおきかえを検討してもよさそう

developer.mozilla.org

他参考

https://coliss.com/articles/build-websites/operation/css/new-css-logical-properties.html

【Zod】Zodiosとは

ZodiosというAPIクライアントを知ったので調べた

github.com

ZodiosはAPIのパラメータやレスポンスをZodで型をつけたものとして扱えるというもの

Zodを使っている人は重宝しそう

kaniさんの記事が参考になる   oisham.hatenablog.com

axios依存の API クライアントであるが、fetchをプラグインとして使うことは可能みたい

Zodiosでの宣言例

import { Zodios } from "@zodios/core";
import { z } from "zod";

const apiClient = new Zodios(
  "https://jsonplaceholder.typicode.com",
  // API definition
  [
    {
      method: "get",
      path: "/users/:id", // auto detect :id and ask for it in apiClient get params
      alias: "getUser", // optionnal alias to call this endpoint with it
      description: "Get a user",
      response: z.object({
        id: z.number(),
        name: z.string(),
      }),
    },
  ],
);

こう宣言しておくと、呼び出す時にパスの候補を出してくれたり、レスポンスに型補完がついて便利になる

書き心地もよさそうなので、使ってみたい

【Lottie】Lottieとは

LottieというAirbnbが開発しているアニメーションライブラリを知ったので試してみた

airbnb.design

とりあえずの使い方はこちらにすごく詳しく書かれていた   WebアニメーションはLottieがオススメ!基本の使い方完全ガイド【2020年版】 | PhotoshopVIP

IllustratorやAfterEffectまわりは省略して、それ以降のLottie JSONファイルをもらってからの実装をメモしておく

実装に必要なものは

  • lottie.js
  • Lottie JSONファイル

lottie.js は以下からダウンロードするか、npmインストールする
github.com

もしくはCDN経由で読み込む
bodymovin - Libraries - cdnjs - The #1 free and open source CDN built to make life easier for developers

あとは、次のようにJS内で設定を実装する

  lottie.loadAnimation({
    container: document.getElementById('lottie'), 
    renderer: 'svg',
    loop: true,
    autoplay: true,
    path: 'data.json', // jsonのパスを指定
  });

Lottie JSONファイルはIllustratorやAfterEffectで自作もできるし、以下からフリー素材を選んで使ってもよい

lottiefiles.com

今度自作してみたい

【React】debounce機能の実装

ユーザーが入力したテキストで検索してサジェストするようなコンポーネントをつくりたい

以前、1文字ずつ入力するたびにリクエストを送ってしまうことの対処法はAbortControllerを使えばよいことがわかったので、あとは実際にどういう風にコンポーネントを作るかを考える

uga-box.hatenablog.com

入力したら次から次へとリクエストするのではなく、ユーザーの入力後の1秒後にその時入力されている文字でリクエストするようにしたい

これをdebounce機能ということを知った

zenn.dev

上の記事とちょっと違うのは、1秒後の実行中にもしまた入力が始まればリクエストを中断し、また1秒待つということがやりたい

これを満たす実装をAbortControllersetTimeoutを駆使して考えてみたのが以下

  const handleChange = async (event: React.ChangeEvent<HTMLInputElement>) => {
    if (controller) {
      controller.abort();  // useStateで管理しているAbortControllerインスタンスがあればabortする
    }
    const _controller = new AbortController();  // 以前のAbortControllerは使えないので新しいインスタンスを作成
    setController(_controller);
    const text = event.currentTarget.value;
    setInputValue(text);  // 入力された値は遅延なしで表示させる
    if (text.length >= 1) {
      setIsLoading(true);  // ローディング中
      if (timer) {
        clearTimeout(timer);  // setTimeoutで待機中であれば前回のものは破棄
      }
      setTimer(
        setTimeout(() => {
          searchSuggest(_controller, text);  // 1秒後に入力された文字列で検索
        }, 1000),
      );
    } else {
      // 全て消した時の処理
    }
  };

これで一応やりたいことができた

【Ajv】Ajvとは

Ajv.jsというのを知ったので調べた

Ajv.jsはjsonバリデータ ajv.js.org

以下のように宣言型スキーマを介してバリデーションを行う

const Ajv = require("ajv")
const ajv = new Ajv()

const schema = {
  type: "object",
  properties: {
    foo: {type: "integer"},
    bar: {type: "string"}
  },
  required: ["foo"],
  additionalProperties: false
}

const data = {foo: 1, bar: "abc"}
const valid = ajv.validate(schema, data)
if (!valid) console.log(ajv.errors)

zodと同様の位置付けになるが、スキーマファイルを用意するという点で異なるものだとわかった

【Zod】TypeScript First なバリデーションライブラリ - UGA Boxxx

手書きでスキーマファイル作るのは大変そうな印象だが、軽量で高速であるという特徴があるため、現場にあわせて導入を検討するのはよさそう

【イベント参加ログ】JSConf JP 2022の参加レポ

11/25の開催された JSConf JP 2022の参加レポ

jsconf.jp

ブログ系プラットフォームを開発するときのTIPS

Zennの開発者で有名なCatnoseさんの発表

https://catnose-jsconf2022.pages.dev/1

レッドオーシャンなブログ系サービスの中で勝つための戦略として「パフォーマンス」に注力したという話

いくつかのパターンを紹介していた

  1. ISRでキャッシュする
  2. Cache-Contorl: stale-while-revalidate
  3. 記事の更新と同時にキャッシュをパージ

あとはmarkdownエディタにおける画面レイアウトシフトの対策がやっかいそうだった(2022年11月時点でGitHubでさえ対応しきれていない)

たとえば

  • scriptタグによる埋め込み
  • ツイートの埋め込み

など、だいぶ厳しそうだった

なにかエディタをつくるときには注意点として再度見直したい

OPTIMIZING INTERACTION TO NEXT PAINT (INP)

Interaction to Next Paint (INP)という、何かしらアクションをしてから次のペイントが始まるまでの時間の最適化について興味深いセッション

内容は以下の記事とほぼ同様
web.dev

インタラクションのイベントハンドラーが実行を開始するまで、メインスレッドにおけるブロッキングタスクなどにより入力遅延が発生する

インタラクションは主に、マウスでクリックやデバイスタップ、キーボードのキーを押すことをさしている

ラボツールやweb-vitalsを使ってINPを測定して改善することをおすすめしていた

オプショナルチェーンができるまで

便利なオプショナルチェーンが採用されるまでの話

オプショナルチェーンができるまで 〜仕様と実装〜 - Google スライド

何回か聞いてもTC39のプロセスを忘れてしまうので、またおさらいできてよかった

また、Stage 4 になるまでの議論から実装が(英語だったのでわずかだが)わかった、document.allとかの細かい仕様を気をつけたりと、ほんと大変な作業なんだと感じた

TC39 – Specifying JavaScript.

HONO - ULTRAFAST WEB FRAMEWORK FOR CLOUDFLARE WORKERS, DENO, BUN, AND NODE.JS

Honoというフレームを作っているYusuke Wadaさんの発表

Hono - Ultrafast web framework for Cloudflare Workers, Deno, and Bun.

Hono自体はあとで調べるとして、他に紹介していた超軽量なURLPatternを使ったWeb フレームワークも紹介していて興味があるので、こちらもあとで調べたい

GitHub - yusukebe/pico: Ultra-tiny web framework for Cloudflare Workers and Deno

後半は用事があり参加できず

【Next.js】rewrite機能を使ってルーティングを考える

Next.js(< 13)で次のようなルーティングを行いたい

  • /a-Japanでアクセスされたらlocale=encountry=Japanとしてパラメータを受け取る
  • /ja/a-Japanでアクセスされたらlocale=jacountry=Japanとしてパラメータを受け取る
  • /a-Japan/a-Tokyoでアクセスされたらlocale=encountry=Japancity=Tokyoとしてパラメータを受け取る
  • /ja/a-Japan/a-Tokyoでアクセスされたらlocale=jacountry=Japancity=Tokyoとしてパラメータを受け取る
  • /a-Japan/s-Tokyoでアクセスされたらlocale=encountry=Japanstation=Tokyoとしてパラメータを受け取る
  • /ja/a-Japan/s-Tokyoでアクセスされたらlocale=jacountry=Japanstation=Tokyoとしてパラメータを受け取る

上記はすべて同じページで異なるパラメータを使って取得するデータを変える

いろいろ調べたがよい方法が見つからなかったので独自に考えた

パスの最初の階層によるlocaleの取得は、いわゆる国際化対応でNext.jsでは標準対応しているため簡単にできる

nextjs.org

次にcountrycitystationであるが、これはrewrites機能を使った

nextjs.org

/pages/areaを作成し、

  • /a-Japanでアクセスされたら/area?country=a-Japanになるように
  • /a-Japan/a-Tokyoでアクセスされたら/area?country=a-Japan&city=a-Tokyoになるように
  • /a-Japan/s-Tokyoでアクセスされたら/area?country=a-Japan&station=s-Tokyoになるように

こうなるように、next.config.jsにrewrite設定をした

  async rewrites() {
    return [
      {
        source: "/:country(a-[A-Z]+[a-zA-Z-]*)/:city(a-[A-Z]+[a-zA-Z-]*)",
        destination: "/area?country=:country&city=:city"
      },
      {
        source: "/:country(a-[A-Z]+[a-zA-Z-]*)/:station(s-[A-Z]+[a-zA-Z-]*)",
        destination: "/area?country=:country&station=:station"
      },
      {
        source: "/:country(a-[A-Z]+[a-zA-Z-]*)",
        destination: "/area?country=:country"
      }
  }

あとはgSSPa-などのプレフィックスを処理することで、やりたいルーティングにすることができた