技術の変遷は秋の空、ワイの興味は飽きの空。時々OSSとテスト。

2023-08-08

ブログ作成で利用した技術について

#Astro#React#Storybook
astro_with_react

みなさん初めまして、ダイの大冒険という漫画が大好きなbun913です。

みなさんフロントエンドもキャッチアップしていますか?私は頑張っている最中です。

このブログを作成する際の大きなモチベーションに「静的なサイト作成を通じてReactや周辺技術のキャッチアップをする」というのがありました。

そのため今回は以下の技術を(無駄に)活用しながら、快適に開発ができたので軽くご紹介したいと思います。

「Zennと似たような執筆体験」を目指した結果、本家には劣りますが割と快適に書ける環境ができました。

Astro

静的なサイトを作るのに適したなんでも入りのFWとなります。

Astroアイランドという考え方があり、基本は静的なページとしつつも一部を動的なパーツとすることができます。

このサイトは基本的にほとんど静的なページなのですが、ヘッダーなどの一部のパーツについては状態を持つようにしています。

Astro自体でコンポーネントを作成できるのですが、今回はReactで作ったコンポーネントを呼び出してパラメーターを渡す役割に終始してもらうことにしました。

hoge.astroという形式のファイルにAstron記法で記述するのですが、以下のようにVueReactに慣れている方であればすぐに基本を理解できそうな形でした。

---
import { BlogListElm } from "../../molecules/BlogListElm/BlogListElm"
const { title, tags, date, slug } = Astro.props.blog
---

<BlogListElm title={title}, tags={tags}, date={date}, slug={slug} />

また、Cloudflare Pagesとの兼ね合いもよく、容易にカスタムドメインでサイトを公開できました。(ドメイン購入もCloudflareでできるのも良いですね)

体感ですがスピードもとても早く感じるので、結果的にとても良い選択でした。

React + Storybook + Jest

今回のブログはこちらを使いたいというのがメインの理由でした。

とはいえ、静的なパーツが多いのでReactの状態管理をガッツリ学習できたわけではありませんが、Storybookとテストを組み合わせることができたのは非常によかったです。

巷ではStorybook駆動開発が話題になっていますが、その良さを少しでも体感できたのはよかったです。

まずこれまでは小さなコンポーネントを作っても、それを開発画面にレンダリングするまではどのような見た目になるかわかりませんでした。

ところがStoryBookでは以下のようにローカルの環境でもどのようなコンポーネントがあるのか容易にカタログ化できます。

StorybookImage1

さらにコンポーネントに渡す引数や状態が変わることでどのような見た目の変化(挙動の変化)をするのか容易に把握できます。

試しにパラメーターを切り替えると、見た目が変わることを容易に把握できました。

StorybookImage2

しかもこの挙動も以下のように数行書いてあげるだけだったので非常に楽です。

SnsIcon.stories.tsx
const meta = {
  title: "atoms/Link/SNSLink",
  component: IconLink,
  argTypes: {
    icon: {
      options: iconNames,
      control: {
        type: "radio",
      },
    },
    url: {
      options: [GitHubUrl, ZennUrl, SpeakerDeckUrl, DevIoURL],
      control: {
        type: "select",
      },
    },
  },
} satisfies Meta<typeof IconLink>

export default meta

type Story = StoryObj<typeof IconLink>

export const DefaultStory: Story = {
  args: {
    url: GitHubUrl,
    icon: "GitHub",
  },
}

このStoryでは省いていますが、play関数を記載することでStorybook上でインタラクションのテストも可能です。

Jest側にStorybookを取り込んでplay関数後のあるべき状態について書くこともできるため、色々とやりやすそうです。

このサイトでは一部のStorybookをJest(testing-library)で利用しています。

describe("NormalStory", () => {
  it("前のページのリンクも次のページのリンクもある", async () => {
    const { container } = render(<NormalStory />)
    // aタグの数が2
    await NormalStory.play({ canvasElement: container })
    expect(container.querySelectorAll("a")).toHaveLength(2)
    // AタグとしてPrevのリンクが取れる
    const prev = container.querySelector('a[href="/page/1"]')
    expect(prev!.tagName).toBe("A")
    // AタグとしてNextのリンクが取れる
    const next = container.querySelector('a[href="/page/3"]')
    expect(next!.tagName).toBe("A")
  })
})

まとめ

  • Storybookは使わない理由がないほど便利
  • Cloudflareも非常に使いやすかったのでもっと勉強したい
  • CSSは今も昔もわからないので苦戦中

なお、ここでは省きましたがこのサイトではテストの自動化や静的解析の自動化もCIとして組み込んでいます。

開発の初期にやっておいてよかったと思ったので、次回以降ご紹介したいと思います。

最後まで読んでいただきありがとうございました。bun913でした。