pluginSsg

React の JSX・TSX ファイルを静的な HTML に変換するプラグイン。

Table of Contents

How To Use

./minista.config.js
import { pluginSsg } from "minista"

export default {
  plugins: [pluginSsg()],
}
./src/pages/index.jsx
export default function () {
  return <h1>Hello!</h1>
}

Options

Default
pluginSsg({
  layout: "/src/layouts/index.{tsx,jsx}",
  src: ["/src/pages/**/*.{tsx,jsx,mdx,md}"],
  srcBases: ["/src/pages"],
})

layout

  • 型: string
  • デフォルト: "/src/layouts/index.{tsx,jsx}"

すべてのページテンプレートをラップするコンポーネントの場所を指定します。対象ファイルは Vite の機能で glob import され最初に見つかったファイルが使用されます。

src

  • 型: string[]
  • デフォルト: ["/src/pages/**/*.{tsx,jsx,mdx,md}"]

ページテンプレートを glob 形式で指定します。対象ファイルは Vite の機能で glob import されます。

srcBases

  • 型: string[]
  • デフォルト: ["/src/pages"]

ページテンプレートを URL に変換する際に省くパス。前方一致で削除されます。

<head> タグ内に title meta link script style を設置できるコンポーネント。

  • htmlAttributes: html の属性を変更
  • bodyAttributes: body の属性を変更
  • key: タグを後のものに差し替え
./src/pages/index.jsx
import { Head } from "minista/head"

export default function () {
  return (
    <>
      <Head
        htmlAttributes={{ lang: "en" }}
        bodyAttributes={{ class: "body-class" }}
      >
        <title>Index</title>
        <meta name="description" content="base" key="desc" />
        <meta name="description" content="override" key="desc" />
      </Head>
      <h1>Index</h1>
    </>
  )
}

Layout

すべてのページテンプレートをラップする JSX 形式のテンプレート。

  • /src/layouts/index.{tsx,jsx}: デフォルトで使用されるファイル
  • export default: 使用されるコンポーネント
  • export const metadata: ページとマージして使えるデータ
  • props: LayoutProps: ページとマージされたデータ
./src/layouts/index.tsx
import type { Metadata, LayoutProps } from "minista/types"

export const metadata: Metadata = {
  title: "Layout Title",
}

export default function (props: LayoutProps) {
  return (
    <>
      {props.url /* Page URL */}
      {props.title /* Override with Page Title */}
      {props.draft /* boolean */}
      {props.children /* Page Contents */}
    </>
  )
}

Page

各 HTML ページの元となる JSX 形式のテンプレート。

  • /src/pages/**/*.{tsx,jsx}: デフォルトで使用されるファイル
  • export default: 使用されるコンポーネント
  • export const metadata: レイアウトとマージして使えるデータ
  • props: PageProps: レイアウトとマージされたデータ
./src/pages/index.tsx
import type { Metadata, PageProps } from "minista/types"

export const metadata: Metadata = {
  title: "Page Title",
  draft: false, // true = Don't build the page
}

export default function (props: PageProps) {
  return (
    <>
      {props.url /* Page URL */}
      {props.title /* Override Layout Title */}
      {props.draft /* boolean */}
    </>
  )
}

Fetch

リモートのデータを取得してページを生成することが可能です。

  • getStaticData(): ページ生成前に非同期処理を実行
  • /src/pages/[foo]/[bar].{tsx,jsx}: 動的ルーティング
./src/pages/index.tsx
import type { StaticData, PageProps } from "minista/types"

export async function getStaticData(): Promise<StaticData> {
  const apiUrl = "https://api.github.com/repos/qrac/minista/issues"
  const apiParamsQuery = "?state=all&creator=qrac&per_page=5"
  const response = await fetch(apiUrl + apiParamsQuery)
  const data = await response.json()
  return {
    props: {
      issues: data,
    },
  }
}

type PagePropsWithIssues = PageProps & {
  issues?: { title: string; number: number }[]
}

export default function (props: PagePropsWithIssues) {
  const langList = ["en", "ja"]
  return (
    <>
      <h1>Issues</h1>
      {langList.map((lang) => (
        <div key={lang}>
          <h2>lang: {lang}</h2>
          <ul>
            {props.issues?.map((item, index) => (
              <li key={index}>
                <a href={`/issues/${lang}/${item.number}`}>{item.title}</a>
              </li>
            ))}
          </ul>
        </div>
      ))}
    </>
  )
}
./src/pages/issues/[lang]/[number].tsx
import type { StaticData, PageProps } from "minista/types"

export async function getStaticData(): Promise<StaticData[]> {
  const apiUrl = "https://api.github.com/repos/qrac/minista/issues"
  const apiParamsQuery = "?state=all&creator=qrac&per_page=5"
  const response = await fetch(apiUrl + apiParamsQuery)
  const data = await response.json()
  const langList = ["en", "ja"]
  return langList
    .map((lang) =>
      data.map((item: PagePropsMergedIssue) => ({
        props: item,
        paths: { lang, number: item.number },
      }))
    )
    .flat()
}

type PagePropsMergedIssue = PageProps & {
  title: string
  body: string
  number: number
}

export default function (props: PagePropsMergedIssue) {
  return (
    <>
      <h1>{props.title}</h1>
      <div>{props.body}</div>
    </>
  )
}

Merge Types

Metadata PageProps LayoutProps には独自のプロパティを追加できますが、TypeScript のモジュール拡張を使用することで型も追加できます。

./types.d.ts
import "minista/types"

declare module "minista/types" {
  interface Metadata {
    foo?: string
  }
  interface PageProps {
    foo: string
  }
  interface LayoutProps {
    foo: string
  }
}
./tsconfig.json
{
  "compilerOptions": {
    "types": ["minista/client", "./types.d.ts"]
  }
}