v4からv5への移行

ここではminista v4からv5への移行方法を説明します。

v3以前を利用している場合は、先にv3→v4の移行手順(日本語版)を参照してください。

Table of Contents

エージェントを使って移行する

エージェントにこのページのURLを渡して、v4からv5への移行を依頼できます。URLと合わせて、対象のプロジェクトと確認してほしいことを伝えてください。プロジェクトを開いた状態なら、次のように依頼できます。

このプロジェクトをminista v4からv5へ移行してください。
以下の移行ガイドを読み、依存関係・設定・コードを更新してください。
https://minista.dev/ja/docs/reference/migration

表示や機能を維持し、移行後に型チェック・ビルド・プレビューを確認してください。
変更点と、確認できなかった項目を報告してください。

v5への更新後はnpx minista agentsで、インストール済みのバージョンに対応するエージェント向けガイドを取得できます。エージェントの使い方はエージェントを使った制作を参照してください。

対応環境と基本設定

Node.jsは^20.19.0 || >=22.12.0、Viteは^8.1.0が必要です。

ReactとReact DOMのpeerDependenciesを>=19.0.0へ変更しました。React 18のサポートと専用テストを終了し、React 19を検証の基準とします。React 18を利用しているプロジェクトは、v5への移行時に両方を19以降へ更新してください。

TypeScriptを使用する場合は、@types/reactと@types/react-domもReactのバージョンに合わせて更新してください。

基本的なVite設定は継続して使用できます。MDX・Bundle・Entryの公開プラグインAPIは以下の手順でSSGへ移してください。内部ビルドは、Vite CLIをHTML生成用とブラウザ用に2回起動する方式から、HTML生成用の環境とブラウザ向けの環境を一つのViteアプリケーションビルドで順にビルドする方式へ変更されました。

SSGへ統合されたプラグインの設定を移したうえで、コマンドに--oneBuildが残っている場合は削除してください。v5ではこのオプションを指定するとMINISTA_CLI_OPTION_REMOVEDで終了します。

- minista build --oneBuild
+ minista build

v5では次の機械可読な出力とコマンドを利用できます。

  • minista check [--json]: ルートとページとgetStaticData()を検査
  • minista inspect [--json]: 元ファイルからProject Graphを表示
  • minista inspect --manifest [--json]: ビルド済みmanifestだけを表示
  • minista explain <node-id> [--json]: Graphの要素の関係を説明

作業用ディレクトリはルートにpackage.jsonがあればnode_modules/.minista、なければ.ministaです。旧バージョンでルート直下に保存したデータは自動移動・削除・読込しません。更新後にcheckやビルドで再生成してください。minista agents --jsonで保存先を取得でき、minista agents --writeで既存プロジェクトへAIエージェント向けの案内を追加できます。

  • node_modules/.minista/manifest.json: ビルド時のプロジェクト構成と出力情報
  • node_modules/.minista/diagnostics.json: 直近の検査・ビルドの診断

通常のCLI実行にminista自身の事前ビルドは必要ありません。

pluginMdx/pluginBundleのSSG統合

pluginMdx()とpluginBundle()をimportとplugins配列から削除し、それぞれの設定をpluginSsg()のmdxとbundleへ移してください。

vite.config.js
import { defineConfig, pluginSsg } from "minista"

export default defineConfig({
  plugins: [
    pluginSsg({
      mdx: { frontmatter: { name: "metadata" } },
      bundle: { outName: "bundle" },
    }),
  ],
})

MDX・Markdownはデフォルトで有効です。不要な場合はmdx: falseを指定してください。Bundle独自のsrcは廃止したため、ページの探索範囲はpluginSsg({ src: [...] })へまとめます。useExportCssも廃止し、ページとLayoutがimportするCSSは常に出力します。CSS ModulesはHTML生成用の環境と同じ変換結果を使用します。

詳細はpluginSsgを参照してください。

pluginEntryのSSG統合

v5ではpluginEntry()を削除しました。HTMLのCSS・JavaScript・画像参照はpluginSsg()だけでビルドされます。importとplugins配列からpluginEntryを削除してください。既存の参照やViteの出力設定はそのまま利用でき、publicのCSS・JSとも併用できます。

vite.config.js
import { defineConfig, pluginSsg } from "minista"

export default defineConfig({ plugins: [pluginSsg()] })

JSがimportしたCSSへscriptのURLが誤って置換される場合と、互換ビルドでpublic CSSが重複挿入される場合も修正しました。

pluginSsg()の戻り値は内部Viteプラグインの配列になりました。通常のplugins: [pluginSsg()]は変更不要です。独自コードで戻り値を直接調べている場合は、配列を展開してから各プラグインを参照してください。

HTMLの言語とレイアウト

htmlのデフォルトの言語をjaからenへ変更しました。日本語のサイトでは、lang="ja"を明示してください。

v5ではLayoutにhtml head bodyを書いて、HTML全体の構造や属性を編集できます。次のレイアウトは、そのままページのHTMLとして出力されます。

src/layouts/index.tsx
import type { LayoutProps } from "minista/types"

export default function Layout({ title, children }: LayoutProps) {
  return (
    <html lang="ja">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width" />
        <title>{title}</title>
      </head>
      <body>{children}</body>
    </html>
  )
}

HTML全体を書かないレイアウトを継続する場合は、従来どおりHeadのhtmlAttributesで指定できます。

src/layouts/index.tsx
import { Head } from "minista"
import type { LayoutProps } from "minista/types"

export default function Layout({ children }: LayoutProps) {
  return (
    <>
      <Head htmlAttributes={{ lang: "ja" }} />
      <main>{children}</main>
    </>
  )
}

構造の編集はレイアウト、ページごとのタイトルやmeta要素の設定はHeadを参照してください。

Beautifyの圧縮とファイル名の設定

v4のpluginBeautify()は、ファイル名にハッシュを付けた後でもJSやCSSの内容を書き換えていました。そのため、ファイル名のハッシュと最終的な内容が一致しない場合がありました。v5では整形のタイミングを見直し、出力設定が整形と両立しない場合はエラーにします。

HTMLに加えてJSとCSSも整形する場合は、次のように設定してください。

vite.config.js
import { defineConfig, pluginSsg, pluginBeautify } from "minista"

export default defineConfig({
  plugins: [pluginSsg(), pluginBeautify()],
  build: {
    sourcemap: false,
    cssMinify: false,
    rolldownOptions: {
      output: {
        minify: false,
        assetFileNames: "assets/[name][extname]",
      },
    },
  },
})
  • JSはハッシュの計算前に整形します。整形後の圧縮を防ぐため、build.rolldownOptions.output.minify: falseが必要です。build.minify: falseだけでは、Rolldownの処理をすべて無効にできません。JSのentryFileNamesとchunkFileNamesには引き続き[hash]を使えます。
  • CSSはファイル名が決まった後に整形します。ハッシュと内容の不一致を避けるため、assetFileNamesには[hash]を含まない文字列を指定してください。この設定は画像などのアセット名にも適用されます。cssMinify: falseでCSSの圧縮も無効にします。
  • 整形後の位置に対応するソースマップを生成できないため、JSやCSSを整形する場合はソースマップを無効にしてください。

HTMLだけを整形する場合は、対象を絞ればJSやCSSの出力設定を変更する必要はありません。

vite.config.js
import { defineConfig, pluginSsg, pluginBeautify } from "minista"

export default defineConfig({
  plugins: [pluginSsg(), pluginBeautify({ src: ["**/*.html"] })],
})

設定と診断の詳細はpluginBeautifyを参照してください。

画像の先読み設定の移動

removeImagePreloadをpluginBeautifyからpluginSsgへ移します。旧オプションの明示指定はMINISTA_BEAUTIFY_OPTION_MOVEDになります。

vite.config.js
import { defineConfig, pluginSsg } from "minista"

export default defineConfig({
  plugins: [pluginSsg({ removeImagePreload: false })],
})

SSGの既定値はtrueです。以前Beautifyを使わなかったプロジェクトも、開発時/ビルドともにReactのレンダラーによる画像の先読みを除去します。保持する場合は上記のfalseを指定してください。従来のbody直下限定からレンダラーの出力全体へ対象が変わるため、Layoutのheadへ直接書いた画像の先読みはHead APIへ移すと保持できます。Beautifyの対象globでpreloadを制御する方法は終了します。

HTMLからのアセット参照

SSGに統合したEntry機能の書換え対象を収集対象と同じlink[href]、script[src]、img[src]、img[srcset]、source[srcset]、use[href]へ揃えました。別の要素で収集されたURLと同じ値でも、meta[content]、video[poster]、a[href]などの対象外属性は変更しません。これらの属性で生成アセットを使う場合は、SSGのモジュールのimportから得たURLかpublicアセットのURLを指定してください。

エントリーがimportするCSSは参照ページにだけ一度挿入します。別ページのエントリーを通じた暗黙のCSS適用に依存していた場合は、対象ページ/LayoutからCSSをimportするか、明示的なstylesheet linkを追加してください。//で始まる外部URLは収集せず、CDNの絶対URLを指定したbaseはプロトコルを保持します。クエリ/フラグメントは保持しますが、Viteのモジュール変換クエリとしては解釈しません。詳細はpluginSsgのHTMLアセット参照を参照してください。

SVGの属性保持とファイルの欠落

pluginSvg()はSVGO最適化後の描画用ルート属性を保持します。fill/strokeやサイズを元ファイルで指定している場合は出力へ反映されます。上書きする場合はSvgの同名propsを指定してください。style/classNameは属性全体を置き換えます。

存在しない元ファイルを黙って残す動作は廃止し、MINISTA_SVG_SOURCE_NOT_FOUND エラーでビルドを失敗させます。srcはプロジェクトルート相対として解決されます。開発中の元ファイル変更は再起動なしで反映されます。

SVGの内部IDとスプライトの重複ID

内部IDは決定的な接頭辞付きに変わります。元IDへの外部CSS/JavaScript参照を避け、classや明示propsを使用してください。Spriteの公開シンボルIDは維持しますが、重複は上書きせずMINISTA_SPRITE_DUPLICATE_SYMBOL エラーになります。衝突するシンボルを改名してください。Spriteは元のルート描画属性と共有defsも保持するようになります。

アーカイブの入力とファイルの欠落

pluginArchive()およびarchives[].srcDirの省略時は、固定のdistではなく解決済みbuild.outDirを入力にします。例えばbuild.outDir: "output"ならoutputを圧縮し、既定の出力名はoutput/dist.zipです。従来どおり別のdistを入力にしたい場合はsrcDir: "dist"を明示してください。

欠落した入力は空のアーカイブの成功生成ではなくMINISTA_ARCHIVE_SOURCE_NOT_FOUND エラーになり、ディレクトリ以外の指定はMINISTA_ARCHIVE_SOURCE_NOT_DIRECTORY エラーになります。存在する空ディレクトリは引き続き許可します。同じarchivesに設定された全出力パスは前回分も入力から除外し、再ビルド時のアーカイブの入れ子化を防ぎます。

IslandのJavaScript取得と実行

client:visible/client:media/client:idleはハイドレーションだけでなく、コンポーネントのJavaScript取得とモジュール評価も条件成立まで遅延します。コンポーネントのモジュールのトップレベルにある副作用をページ初期化として利用していた場合は、即時実行するscriptへ移してください。client:load/client:onlyはIslandのエントリー実行時に取得を開始します。初期表示用のSSG CSSは維持されます。

移行後の確認

設定と依存関係を更新したら、次の順に確認します。

npx minista check --json
npx minista inspect --json
npx tsc --noEmit
npm run build
npm run preview

TypeScriptを使用しないプロジェクトではtscは不要です。生成HTML、CSS、画像、Islandの操作、納品用アーカイブを確認してください。CMSのデータ取得がある場合は、検査とビルドに必要な環境変数も用意します。

コマンドの詳細はCLI、出力設定は設定リファレンスを参照してください。