コンテンツへスキップ

バックエンド連携

注意

従来のバックエンド(例: Rails、Laravel)で HTML を提供し、Vite をアセット提供に利用したい場合は、Awesome Vite に記載されている既存の連携を参照してください。

カスタム連携が必要な場合は、このガイドの手順に従って手動で設定できます。

  1. Vite の設定で、エントリーを構成し、ビルドマニフェストを有効にします。

    vite.config.js
    js
    export default 
    defineConfig
    ({
    server
    : {
    cors
    : {
    // the origin you will be accessing via browser
    origin
    : 'http://my-backend.example.com',
    }, },
    build
    : {
    // generate .vite/manifest.json in outDir
    manifest
    : true,
    rollupOptions
    : {
    // overwrite default .html entry
    input
    : '/path/to/main.js',
    }, }, })

    モジュールプリロードポリフィルを無効にしていない場合は、エントリーでポリフィルをインポートする必要もあります。

    js
    // add the beginning of your app entry
    import 'vite/modulepreload-polyfill'
  2. 開発時には、サーバーの HTML テンプレートに以下を挿入します(https://:5173 を Vite が実行されているローカル URL に置き換えてください)。

    html
    <!-- if development -->
    <script type="module" src="https://:5173/@vite/client"></script>
    <script type="module" src="https://:5173/main.js"></script>

    アセットを適切に提供するために、2つのオプションがあります。

    • 静的アセットのリクエストを Vite サーバーにプロキシするようにサーバーが構成されていることを確認します。
    • server.origin を設定して、生成されたアセット URL が相対パスではなくバックエンドサーバーの URL を使用して解決されるようにします。

    これは、画像などのアセットが適切に読み込まれるために必要です。

    注: @vitejs/plugin-react を使用して React を利用している場合は、プラグインが提供している HTML を変更できないため、上記のスクリプトの前にこれも追加する必要があります(https://:5173 を Vite が実行されているローカル URL に置き換えてください)。

    html
    <script type="module">
      import RefreshRuntime from 'https://:5173/@react-refresh'
      RefreshRuntime.injectIntoGlobalHook(window)
      window.$RefreshReg$ = () => {}
      window.$RefreshSig$ = () => (type) => type
      window.__vite_plugin_react_preamble_installed__ = true
    </script>
  3. 本番環境: vite build を実行すると、他のアセットファイルとともに .vite/manifest.json ファイルが生成されます。マニフェストファイルの例は次のとおりです。

    .vite/manifest.json
    json
    {
      "_shared-B7PI925R.js": {
        "file": "assets/shared-B7PI925R.js",
        "name": "shared",
        "css": ["assets/shared-ChJ_j-JJ.css"]
      },
      "_shared-ChJ_j-JJ.css": {
        "file": "assets/shared-ChJ_j-JJ.css",
        "src": "_shared-ChJ_j-JJ.css"
      },
      "baz.js": {
        "file": "assets/baz-B2H3sXNv.js",
        "name": "baz",
        "src": "baz.js",
        "isDynamicEntry": true
      },
      "views/bar.js": {
        "file": "assets/bar-gkvgaI9m.js",
        "name": "bar",
        "src": "views/bar.js",
        "isEntry": true,
        "imports": ["_shared-B7PI925R.js"],
        "dynamicImports": ["baz.js"]
      },
      "views/foo.js": {
        "file": "assets/foo-BRBmoGS9.js",
        "name": "foo",
        "src": "views/foo.js",
        "isEntry": true,
        "imports": ["_shared-B7PI925R.js"],
        "css": ["assets/foo-5UjPuW-k.css"]
      }
    }
    • マニフェストは Record<name, chunk> 構造です。
    • エントリーチャンクまたは動的エントリーチャンクの場合、キーはプロジェクトルートからの相対的な src パスです。
    • エントリーでないチャンクの場合、キーは _ をプレフィックスとする生成されたファイルのベース名です。
    • build.cssCodeSplitfalse の場合に生成される CSS ファイルの場合、キーは style.css です。
    • チャンクには、静的および動的インポートに関する情報(どちらもマニフェスト内の対応するチャンクにマップされるキー)と、対応する CSS およびアセットファイル(もしあれば)が含まれます。
  4. このファイルを使用して、ハッシュ化されたファイル名でリンクやプリロードディレクティブをレンダリングできます。

    適切なリンクをレンダリングするための HTML テンプレートの例を次に示します。ここでの構文は説明のためだけであり、サーバーのテンプレート言語に置き換えてください。importedChunks 関数は説明のためのものであり、Vite によって提供されるものではありません。

    html
    <!-- if production -->
    
    <!-- for cssFile of manifest[name].css -->
    <link rel="stylesheet" href="/{{ cssFile }}" />
    
    <!-- for chunk of importedChunks(manifest, name) -->
    <!-- for cssFile of chunk.css -->
    <link rel="stylesheet" href="/{{ cssFile }}" />
    
    <script type="module" src="/{{ manifest[name].file }}"></script>
    
    <!-- for chunk of importedChunks(manifest, name) -->
    <link rel="modulepreload" href="/{{ chunk.file }}" />

    具体的には、HTML を生成するバックエンドは、マニフェストファイルとエントリーポイントが与えられた場合、以下のタグを含める必要があります。

    • エントリーポイントチャンクの css リスト内の各ファイルに対する <link rel="stylesheet"> タグ
    • エントリーポイントの imports リスト内のすべてのチャンクを再帰的にたどり、インポートされた各チャンクの各 CSS ファイルに対して <link rel="stylesheet"> タグを含めます。
    • エントリーポイントチャンクの file キーのタグ(JavaScript の場合は <script type="module">、CSS の場合は <link rel="stylesheet">
    • オプションとして、各インポートされた JavaScript チャンクの file に対する <link rel="modulepreload"> タグ。ここでも、エントリーポイントチャンクから始まるインポートを再帰的にたどります。

    上記の例のマニフェストに従って、エントリーポイント views/foo.js に対して、本番環境で以下のタグを含める必要があります。

    html
    <link rel="stylesheet" href="assets/foo-5UjPuW-k.css" />
    <link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" />
    <script type="module" src="assets/foo-BRBmoGS9.js"></script>
    <!-- optional -->
    <link rel="modulepreload" href="assets/shared-B7PI925R.js" />

    一方、エントリーポイント views/bar.js に対しては以下を含める必要があります。

    html
    <link rel="stylesheet" href="assets/shared-ChJ_j-JJ.css" />
    <script type="module" src="assets/bar-gkvgaI9m.js"></script>
    <!-- optional -->
    <link rel="modulepreload" href="assets/shared-B7PI925R.js" />
    importedChunks の擬似実装

    TypeScript での importedChunks の擬似実装の例(これはお使いのプログラミング言語とテンプレート言語に適応させる必要があります)。

    ts
    import type { Manifest, ManifestChunk } from 'vite'
    
    export default function importedChunks(
      manifest: Manifest,
      name: string,
    ): ManifestChunk[] {
      const seen = new Set<string>()
    
      function getImportedChunks(chunk: ManifestChunk): ManifestChunk[] {
        const chunks: ManifestChunk[] = []
        for (const file of chunk.imports ?? []) {
          const importee = manifest[file]
          if (seen.has(file)) {
            continue
          }
          seen.add(file)
    
          chunks.push(...getImportedChunks(importee))
          chunks.push(importee)
        }
    
        return chunks
      }
    
      return getImportedChunks(manifest[name])
    }

MIT ライセンスで公開。(083ff36d)