跳到主要內容

資產打包(Vite)

📝 此頁面為 Laravel 官方文檔的繁體中文翻譯。查看原始英文版本

資產打包(Vite)

簡介

Vite 是一個現代化的前端建置工具,提供極快的開發環境,並將您的程式碼打包用於生產環境。在使用 Laravel 建立應用程式時,您通常會使用 Vite 來將應用程式的 CSS 和 JavaScript 檔案打包成可供生產環境使用的資源。

Laravel 透過提供官方外掛和 Blade 指令來載入開發和生產環境的資源,從而與 Vite 無縫整合。

安裝與設定

[!NOTE] 以下文件討論如何手動安裝和配置 Laravel Vite 外掛。但是,Laravel 的入門套件已經包含了所有這些脚手架,是開始使用 Laravel 和 Vite 的最快方式。

安裝 Node

在執行 Vite 和 Laravel 外掛之前,您必須確保已安裝 Node.js(16+)和 NPM:

node -v
npm -v

您可以使用來自官方 Node 網站的簡單圖形安裝程式輕鬆安裝最新版本的 Node 和 NPM。或者,如果您正在使用 Laravel Sail,則可以透過 Sail 呼叫 Node 和 NPM:

./vendor/bin/sail node -v
./vendor/bin/sail npm -v

安裝 Vite 與 Laravel 外掛

在新的 Laravel 安裝中,您會在應用程式目錄結構的根目錄中找到一個 package.json 檔案。預設的 package.json 檔案已經包含了開始使用 Vite 和 Laravel 外掛所需的一切。您可以透過 NPM 安裝應用程式的前端依賴項:

npm install

配置 Vite

Vite 是透過專案根目錄中的 vite.config.js 檔案進行配置的。您可以根據需要自由自訂此檔案,並且還可以安裝應用程式所需的任何其他外掛,例如 @vitejs/plugin-react@sveltejs/vite-plugin-svelte@vitejs/plugin-vue

Laravel Vite 外掛要求您指定應用程式的入口點。這些可以是 JavaScript 或 CSS 檔案,並包括諸如 TypeScript、JSX、TSX 和 Sass 等預處理語言。

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel([
            'resources/css/app.css',
            'resources/js/app.js',
        ]),
    ],
});

如果您正在建立 SPA,包括使用 Inertia 建立的應用程式,Vite 在不使用 CSS 入口點的情況下效果最佳:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel([
            'resources/css/app.css', // [tl! remove]
            'resources/js/app.js',
        ]),
    ],
});

相反,您應透過 JavaScript 匯入 CSS。通常,這將在應用程式的 resources/js/app.js 檔案中完成:

import './bootstrap';
import '../css/app.css'; // [tl! add]

Laravel 外掛還支援多個入口點和進階配置選項,例如 SSR 入口點

使用安全開發伺服器

如果您的本地開發 Web 伺服器透過 HTTPS 提供應用程式服務,您在連接到 Vite 開發伺服器時可能會遇到問題。

如果您正在使用 Laravel Herd 並且已保護該網站,或者您正在使用 Laravel Valet 並且已對應用程式執行安全命令,則 Laravel Vite 外掛將自動偵測並為您使用產生的 TLS 憑證。

如果您使用與應用程式目錄名稱不匹配的主機保護了網站,則可以在應用程式的 vite.config.js 檔案中手動指定主機:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            // ...
            detectTls: 'my-app.test', // [tl! add]
        }),
    ],
});

使用其他 Web 伺服器時,您應產生受信任的憑證並手動配置 Vite 使用產生的憑證:

// ...
import fs from 'fs'; // [tl! add]

const host = 'my-app.test'; // [tl! add]

export default defineConfig({
    // ...
    server: { // [tl! add]
        host, // [tl! add]
        hmr: { host }, // [tl! add]
        https: { // [tl! add]
            key: fs.readFileSync(`/path/to/${host}.key`), // [tl! add]
            cert: fs.readFileSync(`/path/to/${host}.crt`), // [tl! add]
        }, // [tl! add]
    }, // [tl! add]
});

如果您無法為系統產生受信任的憑證,則可以安裝並配置 @vitejs/plugin-basic-ssl 外掛。使用不受信任的憑證時,您需要在執行 npm run dev 命令時,透過瀏覽器中控制台的「Local」連結來接受 Vite 開發伺服器的憑證警告。

在 WSL2 上的 Sail 中執行開發伺服器

在 Windows Subsystem for Linux 2(WSL2)上的 Laravel Sail 中執行 Vite 開發伺服器時,應在您的 vite.config.js 檔案中新增以下配置,以確保瀏覽器可以與開發伺服器通訊:

// ...

export default defineConfig({
    // ...
    server: { // [tl! add:start]
        hmr: {
            host: 'localhost',
        },
    }, // [tl! add:end]
});

如果在開發伺服器執行時您的檔案變更未反映在瀏覽器中,您可能還需要配置 Vite 的 server.watch.usePolling 選項

載入腳本與樣式

配置好 Vite 入口點後,您現在可以在應用程式根模板的 <head> 中添加的 @vite() Blade 指令中引用它們:

<!DOCTYPE html>
<head>
    {{-- ... --}}

    @vite(['resources/css/app.css', 'resources/js/app.js'])
</head>

如果您透過 JavaScript 匯入 CSS,則只需要包含 JavaScript 入口點:

<!DOCTYPE html>
<head>
    {{-- ... --}}

    @vite('resources/js/app.js')
</head>

@vite 指令將自動偵測 Vite 開發伺服器並注入 Vite 客戶端以啟用熱模組替換。在建置模式下,該指令將載入您編譯和版本化的資源,包括任何匯入的 CSS。

如果需要,您也可以在呼叫 @vite 指令時指定編譯資源的建置路徑:

<!doctype html>
<head>
    {{-- Given build path is relative to public path. --}}

    @vite('resources/js/app.js', 'vendor/courier/build')
</head>

內聯資源

有時可能需要包含資源的原始內容,而不是連結到資源的版本化 URL。例如,在將 HTML 內容傳遞給 PDF 產生器時,您可能需要將資源內容直接包含到頁面中。您可以使用 Vite facade 提供的 content 方法輸出 Vite 資源的內容:

@use('Illuminate\Support\Facades\Vite')

<!doctype html>
<head>
    {{-- ... --}}

    <style>
        {!! Vite::content('resources/css/app.css') !!}
    </style>
    <script>
        {!! Vite::content('resources/js/app.js') !!}
    </script>
</head>

執行 Vite

有兩種方式可以執行 Vite。您可以透過 dev 命令執行開發伺服器,這在本地開發時很有用。開發伺服器將自動偵測檔案的變更並立即反映在任何打開的瀏覽器視窗中。

或者,執行 build 命令將對應用程式的資源進行版本化和打包,使其準備好部署到生產環境:

# Run the Vite development server...
npm run dev

# Build and version the assets for production...
npm run build

如果您在 WSL2 上的 Sail 中執行開發伺服器,可能需要一些額外的配置選項。

使用 JavaScript

別名

預設情況下,Laravel 外掛提供了一個常見的別名,以幫助您快速上手並方便地匯入應用程式的資源:

{
    '@' => '/resources/js'
}

您可以透過在 vite.config.js 配置檔案中新增自己的別名來覆寫 '@' 別名:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel(['resources/ts/app.tsx']),
    ],
    resolve: {
        alias: {
            '@': '/resources/ts',
        },
    },
});

Vue

如果您想使用 Vue 框架來建立前端,則還需要安裝 @vitejs/plugin-vue 外掛:

npm install --save-dev @vitejs/plugin-vue

然後,您可以將此外掛包含在您的 vite.config.js 配置檔案中。在 Laravel 中使用 Vue 外掛時,還需要一些額外的選項:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [
        laravel(['resources/js/app.js']),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

[!NOTE] Laravel 的入門套件已經包含了正確的 Laravel、Vue 和 Vite 配置。這些入門套件提供了開始使用 Laravel、Vue 和 Vite 的最快方式。

React

如果您想使用 React 框架來建立前端,則還需要安裝 @vitejs/plugin-react 外掛:

npm install --save-dev @vitejs/plugin-react

然後,您可以將此外掛包含在您的 vite.config.js 配置檔案中:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';

export default defineConfig({
    plugins: [
        laravel(['resources/js/app.jsx']),
        react(),
    ],
});

您需要確保任何包含 JSX 的檔案都具有 .jsx.tsx 副檔名,並記住在必要時更新入口點,如上所示

您還需要在現有的 @vite 指令旁邊包含額外的 @viteReactRefresh Blade 指令。

@viteReactRefresh
@vite('resources/js/app.jsx')

@viteReactRefresh 指令必須在 @vite 指令之前呼叫。

[!NOTE] Laravel 的入門套件已經包含了正確的 Laravel、React 和 Vite 配置。這些入門套件提供了開始使用 Laravel、React 和 Vite 的最快方式。

Svelte

如果您想使用 Svelte 框架來建立前端,則還需要安裝 @sveltejs/vite-plugin-svelte 外掛:

npm install --save-dev @sveltejs/vite-plugin-svelte

然後,您可以將此外掛包含在您的 vite.config.js 配置檔案中。

import { svelte } from '@sveltejs/vite-plugin-svelte';
import laravel from 'laravel-vite-plugin';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    laravel({
      input: ['resources/js/app.ts'],
      ssr: 'resources/js/ssr.ts',
      refresh: true,
    }),
    svelte(),
  ],
});

[!NOTE] Laravel 的入門套件已經包含了正確的 Laravel、Svelte 和 Vite 配置。這些入門套件提供了開始使用 Laravel、Svelte 和 Vite 的最快方式。

Inertia

Laravel Vite 外掛提供了一個便捷的 resolvePageComponent 函數來幫助您解析 Inertia 頁面元件。以下是該輔助函數在 Vue 3 中的使用範例;但是,您也可以在 React 或 Svelte 等其他框架中使用該函數:

import { createApp, h } from 'vue';
import { createInertiaApp } from '@inertiajs/vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';

createInertiaApp({
  resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
  setup({ el, App, props, plugin }) {
    createApp({ render: () => h(App, props) })
      .use(plugin)
      .mount(el)
  },
});

如果您在 Inertia 中使用 Vite 的程式碼分割功能,我們建議配置資源預先擷取

[!NOTE] Laravel 的入門套件已經包含了正確的 Laravel、Inertia 和 Vite 配置。這些入門套件提供了開始使用 Laravel、Inertia 和 Vite 的最快方式。

URL 處理

在應用程式的 HTML、CSS 或 JS 中使用 Vite 並引用資源時,有幾點需要注意。首先,如果您使用絕對路徑引用資源,Vite 將不會在建置中包含該資源;因此,您應確保該資源存在於您的 public 目錄中。使用專用的 CSS 入口點時,您應避免使用絕對路徑,因為在開發期間,瀏覽器將嘗試從 Vite 開發伺服器載入這些路徑,而不是從您的 public 目錄。

引用相對資源路徑時,您應記住路徑是相對於引用它們的檔案。任何透過相對路徑引用的資源都將由 Vite 重新編寫、版本化和打包。

考慮以下專案結構:

public/
  taylor.png
resources/
  js/
    Pages/
      Welcome.vue
  images/
    abigail.png

以下範例示範了 Vite 如何處理相對和絕對 URL:

<!-- This asset is not handled by Vite and will not be included in the build -->
<img src="/taylor.png">

<!-- This asset will be re-written, versioned, and bundled by Vite -->
<img src="../../images/abigail.png">

使用樣式表

[!NOTE] Laravel 的入門套件已經包含了正確的 Tailwind 和 Vite 配置。或者,如果您想在不使用我們入門套件的情況下使用 Tailwind 和 Laravel,請查看 Tailwind 的 Laravel 安裝指南

所有 Laravel 應用程式都已經包含了 Tailwind 和正確配置的 vite.config.js 檔案。因此,您只需要啟動 Vite 開發伺服器或執行 dev Composer 命令,該命令將同時啟動 Laravel 和 Vite 開發伺服器:

composer run dev

應用程式的 CSS 可以放置在 resources/css/app.css 檔案中。

使用字型

Laravel Vite 外掛可以為您的應用程式提供最佳化的自託管字型。配置字型後,外掛會解析請求的字型檔案,將其作為 Vite 資源發出,產生字型 CSS,並寫入一個可以被 Blade 的 @fonts 指令使用的字型清單。

要配置字型,請從 laravel-vite-plugin/fonts 匯入一個或多個提供者輔助函數,並將它們新增到 Laravel 外掛的 fonts 選項中:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { google } from 'laravel-vite-plugin/fonts';

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.js',
            fonts: [
                google('Inter', {
                    alias: 'sans',
                    weights: [400, 500, 600, 700],
                    styles: ['normal', 'italic'],
                    subsets: ['latin'],
                    display: 'swap',
                    preload: [
                        { weight: 400 },
                        { weight: 700 },
                    ],
                    fallbacks: ['system-ui', 'sans-serif'],
                }),
            ],
        }),
    ],
});

在此範例中,Inter 字型將透過 sans 別名提供。外掛將產生一個 --font-sans CSS 變數和一個 .font-sans 工具類別,用於應用產生的字型堆疊。

字型提供者

Laravel Vite 外掛包含用於 Google Fonts、Bunny Fonts、Fontsource 和本地字型的提供者輔助函數:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { bunny, fontsource, google, local } from 'laravel-vite-plugin/fonts';

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.js',
            fonts: [
                google('Inter', { alias: 'sans' }),
                bunny('Figtree', { alias: 'body' }),
                fontsource('JetBrains Mono', { alias: 'mono' }),
                local('Brand Sans', {
                    alias: 'brand',
                    src: 'resources/fonts/brand-sans',
                }),
            ],
        }),
    ],
});

fontsource 提供者從已安裝的 Fontsource 套件讀取字型。預設情況下,套件名稱是從字型系列派生而來的,例如 @fontsource/jetbrains-mono。如果您的應用程式使用不同的套件名稱,可以使用 package 選項指定它。

本地字型

使用本地字型時,src 選項可以指向單個字型檔案、目錄或 glob 模式。外掛將發現支援的字型檔案,並從其檔案名推斷粗細和樣式:

local('Brand Sans', {
    alias: 'brand',
    src: 'resources/fonts/brand-sans/*.woff2',
})

如果您需要完全控制可用的變體,可以使用 variants 選項明確定義它們:

local('Brand Sans', {
    alias: 'brand',
    variants: [
        { src: 'resources/fonts/BrandSans-Regular.woff2', weight: 400 },
        { src: 'resources/fonts/BrandSans-Italic.woff2', weight: 400, style: 'italic' },
        { src: ['resources/fonts/BrandSans-Bold.woff2', 'resources/fonts/BrandSans-Bold.ttf'], weight: 700 },
    ],
})

字型選項

取決於提供者,字型定義可以接受幾個選項,允許您自訂產生的字型 CSS:

  • alias 定義了 Blade 的 @fonts 指令使用的名稱,預設為字型系列的 slug。
  • variable 定義了產生的 CSS 變數,預設為 --font-{alias}
  • weights 定義了應解析的遠端或 Fontsource 字型粗細,預設為 [400]
  • styles 定義了應解析的遠端或 Fontsource 字型樣式,預設為 ['normal']
  • subsets 定義了應解析的遠端或 Fontsource 字型子集,預設為 ['latin']
  • display 定義了 font-display 值,預設為 swap
  • preload 控制應預先載入哪些 WOFF2 字型變體。此選項可以是 truefalse{ weight, style } 選擇器的陣列。
  • fallbacks 定義了應附加到產生的字型堆疊中的其他後備字型。
  • optimizedFallbacks 嘗試使用可選的 fontaine 套件產生度量調整的後備字型,預設為 true

最佳化後備字型需要 fontaine 套件,該套件預設不安裝。如果您希望 Laravel 產生度量調整的後備字型,應將 fontaine 安裝為開發依賴項:

npm install --save-dev fontaine

如果 fontaine 未安裝或無法讀取字型檔案,Laravel 將跳過該字型的最佳化後備,並繼續使用透過 fallbacks 選項配置的任何字型。

本地字型是從上述 srcvariants 選項解析的,而不是使用 weightsstylessubsets

使用 Blade 和路由

使用 Vite 處理靜態資源

在 JavaScript 或 CSS 中引用資源時,Vite 會自動處理並對它們進行版本化。此外,在建立基於 Blade 的應用程式時,Vite 也可以處理和版本化您僅在 Blade 模板中引用的靜態資源。

但是,要實現這一點,您需要透過在外掛的 assets 選項中指定資源來使 Vite 感知到您的資源。此選項適用於您想直接使用 Vite::asset 引用的靜態檔案。如果您希望 Laravel 產生字型 CSS 和預載入鏈接,請使用 fonts 選項

例如,如果您想處理和版本化儲存在 resources/images 中的所有影像和儲存在 resources/fonts 中的所有字型,應將以下內容新增到您的 Vite 配置中:

laravel({
    input: 'resources/js/app.js',
    assets: ['resources/images/**', 'resources/fonts/**'],
})

這些資源現在將在執行 npm run build 時由 Vite 處理。然後,您可以在 Blade 模板中使用 Vite::asset 方法引用這些資源,該方法將返回給定資源的版本化 URL:

<img src="{{ Vite::asset('resources/images/logo.png') }}">

[!NOTE] 在 Laravel Vite 外掛的版本 3 之前,靜態資源必須使用 import.meta.glob 在應用程式的入口點中匯入。由於 Vite 8 的變更,引入了 assets 選項。

儲存時重新整理

當您的應用程式使用傳統的伺服器端渲染搭配 Blade 時,Vite 可以透過在您對應用程式中的檢視檔案進行變更時自動重新整理瀏覽器來改善您的開發流程。首先,您可以簡單地將 refresh 選項指定為 true

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            // ...
            refresh: true,
        }),
    ],
});

refresh 選項為 true 時,在執行 npm run dev 期間,儲存以下目錄中的檔案將觸發瀏覽器執行完整頁面重新整理:

  • app/Livewire/**
  • app/View/Components/**
  • lang/**
  • resources/lang/**
  • resources/views/**
  • routes/**

監視 routes/** 目錄在您利用 Ziggy 在應用程式前端產生路由鏈接時非常有用。

如果這些預設路徑不適合您的需求,您可以指定自己的監視路徑列表:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            // ...
            refresh: ['resources/views/**'],
        }),
    ],
});

在底層,Laravel Vite 外掛使用 vite-plugin-full-reload 套件,該套件提供了一些進階配置選項來微調此功能的行為。如果您需要這種級別的自訂,可以提供一個 config 定義:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            // ...
            refresh: [{
                paths: ['path/to/watch/**'],
                config: { delay: 300 }
            }],
        }),
    ],
});

別名

在 JavaScript 應用程式中,建立別名以指向經常引用的目錄是很常見的。但是,您也可以透過在 Illuminate\Support\Facades\Vite 類別上使用 macro 方法來建立用於 Blade 的別名。通常,「巨集」應在服務提供者boot 方法中定義:

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Vite::macro('image', fn (string $asset) => $this->asset("resources/images/{$asset}"));
}

定義巨集後,可以在模板中呼叫它。例如,我們可以使用上面定義的 image 巨集來引用位於 resources/images/logo.png 的資源:

<img src="{{ Vite::image('logo.png') }}" alt="Laravel Logo">

資源預先擷取

在使用 Vite 的程式碼分割功能建立 SPA 時,每次頁面導航都會獲取所需的資源。這種行為可能導致 UI 渲染延遲。如果這對您選擇的前端框架來說是一個問題,Laravel 提供了在初始頁面載入時急切地預先擷取應用程式 JavaScript 和 CSS 資源的能力。

您可以透過在服務提供者boot 方法中呼叫 Vite::prefetch 方法來指示 Laravel 急切地預先擷取您的資源:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Vite;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Vite::prefetch(concurrency: 3);
    }
}

在上面的範例中,資源將在每次頁面載入時以最多 3 個並發下載進行預先擷取。您可以修改並發數以滿足應用程式的需求,或者如果應用程式應一次下載所有資源,則可以不指定並發限制:

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Vite::prefetch();
}

預設情況下,預先擷取將在頁面載入事件觸發時開始。如果您想自訂預先擷取何時開始,可以指定 Vite 將監聽的事件:

/**
 * Bootstrap any application services.
 */
public function boot(): void
{
    Vite::prefetch(event: 'vite:prefetch');
}

根據上面的程式碼,預先擷取現在將在您在 window 物件上手動分發 vite:prefetch 事件時開始。例如,您可以在頁面載入後三秒開始預先擷取:

<script>
    addEventListener('load', () => setTimeout(() => {
        dispatchEvent(new Event('vite:prefetch'))
    }, 3000))
</script>

自訂基礎 URL

如果您將 Vite 編譯的資源部署到與應用程式分離的域,例如透過 CDN,則必須在應用程式的 .env 檔案中指定 ASSET_URL 環境變數:

ASSET_URL=https://cdn.example.com

配置資源 URL 後,對資源的所有重寫 URL 將以配置的值作為前綴:

https://cdn.example.com/build/assets/app.9dce8d17.js

請記住,絕對 URL 不會被 Vite 重寫,因此它們不會被添加前綴。

環境變數

您可以透過在應用程式的 .env 檔案中為環境變數添加 VITE_ 前綴來將它們注入到 JavaScript 中:

VITE_SENTRY_DSN_PUBLIC=http://example.com

您可以透過 import.meta.env 物件存取注入的環境變數:

import.meta.env.VITE_SENTRY_DSN_PUBLIC

在測試中停用 Vite

Laravel 的 Vite 整合將在執行測試時嘗試解析您的資源,這需要您執行 Vite 開發伺服器或建置資源。

如果您希望在測試期間模擬 Vite,可以呼叫 withoutVite 方法,該方法可用於任何擴展 Laravel 的 TestCase 類別的測試:

public function test_without_vite_example(): void
{
    $this->withoutVite();

    // ...
}

如果您想為所有測試停用 Vite,可以從基礎 TestCase 類別的 setUp 方法中呼叫 withoutVite 方法:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $this->withoutVite();
    }
}

伺服器端渲染(SSR)

Laravel Vite 外掛使使用 Vite 設置伺服器端渲染變得輕而易舉。首先,在 resources/js/ssr.js 建立一個 SSR 入口點,並透過向 Laravel 外掛傳遞配置選項來指定入口點:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.js',
            ssr: 'resources/js/ssr.js',
        }),
    ],
});

為確保您不會忘記重建 SSR 入口點,我們建議在應用程式的 package.json 中擴充「build」腳本以建立您的 SSR 建置:

"scripts": {
     "dev": "vite",
     "build": "vite build && vite build --ssr"
}

然後,要建置並啟動 SSR 伺服器,您可以執行以下命令:

npm run build
node bootstrap/ssr/ssr.js

如果您正在使用 Inertia 的 SSR,則可以改用 inertia:start-ssr Artisan 命令來啟動 SSR 伺服器:

php artisan inertia:start-ssr

[!NOTE] Laravel 的入門套件已經包含了正確的 Laravel、Inertia SSR 和 Vite 配置。這些入門套件提供了開始使用 Laravel、Inertia SSR 和 Vite 的最快方式。

腳本與樣式標籤屬性

內容安全政策(CSP)Nonce

如果您希望作為內容安全政策的一部分在腳本和樣式標籤上包含nonce 屬性,您可以在自訂中介層中使用 useCspNonce 方法來產生或指定 nonce:

<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Vite;
use Symfony\Component\HttpFoundation\Response;

class AddContentSecurityPolicyHeaders
{
    /**
     * Handle an incoming request.
     */
    public function handle(Request $request, Closure $next): Response
    {
        Vite::useCspNonce();

        return $next($request)->withHeaders([
            'Content-Security-Policy' => "script-src 'nonce-".Vite::cspNonce()."'",
        ]);
    }
}

呼叫 useCspNonce 方法後,Laravel 將自動在所有產生的腳本和樣式標籤上包含 nonce 屬性。

如果您需要在其他地方指定 nonce,包括 Laravel 入門套件中包含的 Ziggy @route 指令,您可以使用 cspNonce 方法檢索它:

@routes(nonce: Vite::cspNonce())

如果您已經有一個想要指示 Laravel 使用的 nonce,可以將 nonce 傳遞給 useCspNonce 方法:

Vite::useCspNonce($nonce);

子資源完整性(SRI)

如果您的 Vite 清單包含資源的 integrity 哈希值,Laravel 將自動在它產生的任何腳本和樣式標籤上添加 integrity 屬性,以實施子資源完整性。預設情況下,Vite 不包含清單中的 integrity 哈希值,但您可以透過安裝 vite-plugin-manifest-sri NPM 外掛來啟用它:

npm install --save-dev vite-plugin-manifest-sri

然後,您可以在 vite.config.js 檔案中啟用此外掛:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import manifestSRI from 'vite-plugin-manifest-sri';

export default defineConfig({
    plugins: [
        laravel({
            // ...
        }),
        manifestSRI(),
    ],
});

如果需要,您也可以自訂可以找到完整性哈希值的清單鍵:

use Illuminate\Support\Facades\Vite;

Vite::useIntegrityKey('custom-integrity-key');

如果您想完全停用此自動偵測,可以將 false 傳遞給 useIntegrityKey 方法:

Vite::useIntegrityKey(false);

任意屬性

如果您需要在腳本和樣式標籤上包含其他屬性,例如 data-turbo-track 屬性,可以透過 useScriptTagAttributesuseStyleTagAttributes 方法來指定它們。通常,這些方法應從服務提供者中呼叫:

use Illuminate\Support\Facades\Vite;

Vite::useScriptTagAttributes([
    'data-turbo-track' => 'reload',
    'async' => true,
    'integrity' => false,
]);

Vite::useStyleTagAttributes([
    'data-turbo-track' => 'reload',
]);

如果您需要有條件地新增屬性,可以傳遞一個回呼,該回呼將接收資源來源路徑、其 URL、其清單區塊和整個清單:

use Illuminate\Support\Facades\Vite;

Vite::useScriptTagAttributes(fn (string $src, string $url, array|null $chunk, array|null $manifest) => [
    'data-turbo-track' => $src === 'resources/js/app.js' ? 'reload' : false,
]);

Vite::useStyleTagAttributes(fn (string $src, string $url, array|null $chunk, array|null $manifest) => [
    'data-turbo-track' => $chunk && $chunk['isEntry'] ? 'reload' : false,
]);

[!WARNING] 在 Vite 開發伺服器執行時,$chunk$manifest 參數將為 null

進階自訂

開箱即用,Laravel 的 Vite 外掛使用適合大多數應用程式的合理慣例;但是,有時您可能需要自訂 Vite 的行為。為了啟用額外的自訂選項,我們提供以下方法和選項,可以用於替代 @vite Blade 指令:

<!doctype html>
<head>
    {{-- ... --}}

    {{
        Vite::useHotFile(storage_path('vite.hot'))
            ->useBuildDirectory('bundle')
            ->useManifestFilename('assets.json')
            ->withEntryPoints(['resources/js/app.js'])
            ->createAssetPathsUsing(function (string $path, ?bool $secure) {
                return "https://cdn.example.com/{$path}";
            })
    }}
</head>

vite.config.js 檔案中,您應指定相同的配置:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            hotFile: 'storage/vite.hot',
            buildDirectory: 'bundle',
            input: ['resources/js/app.js'],
        }),
    ],
    build: {
      manifest: 'assets.json',
    },
});

開發伺服器跨源資源共享(CORS)

如果您在從 Vite 開發伺服器獲取資源時在瀏覽器中遇到跨源資源共享(CORS)問題,您可能需要授予自訂來源對開發伺服器的存取權限。Vite 結合 Laravel 外掛允許以下來源無需任何額外配置:

  • ::1
  • 127.0.0.1
  • localhost
  • *.test
  • *.localhost
  • 專案 .env 中的 APP_URL

為專案允許自訂來源最簡單的方法是確保應用程式的 APP_URL 環境變數與您在瀏覽器中訪問的來源匹配。例如,如果您正在訪問 https://my-app.laravel,則應更新 .env 以匹配:

APP_URL=https://my-app.laravel

如果您需要對來源進行更精細的控制,例如支援多個來源,則應利用 Vite 全面且靈活的內建 CORS 伺服器配置。例如,您可以在專案的 vite.config.js 檔案中的 server.cors.origin 配置選項中指定多個來源:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.js',
            refresh: true,
        }),
    ],
    server: {
        cors: {
            origin: [
                'https://backend.laravel',
                'http://admin.laravel:8566',
            ],
        },
    },
});

您也可以包含正規表示式模式,這在您想為給定的頂級域(例如 *.laravel)允許所有來源時非常有用:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.js',
            refresh: true,
        }),
    ],
    server: {
        cors: {
            origin: [
                /^https?:\/\/.*\.laravel(:\d+)?$/,
            ],
        },
    },
});

修正開發伺服器 URL

Vite 生態系統中的某些外掛假設以正斜杠開頭的 URL 將始終指向 Vite 開發伺服器。但是,由於 Laravel 整合的性質,情況並非如此。

例如,vite-imagetools 外掛在 Vite 提供資源服務時輸出像這樣的 URL:

<img src="/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520">

vite-imagetools 外掛期望輸出 URL 將被 Vite 攔截,然後外掛可以處理所有以 /@imagetools 開頭的 URL。如果您使用期望此行為的外掛,則需要手動修正 URL。您可以在 vite.config.js 檔案中使用 transformOnServe 選項來執行此操作。

在此特定範例中,我們將在產生的程式碼中將所有出現的 /@imagetools 前面加上開發伺服器 URL:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import { imagetools } from 'vite-imagetools';

export default defineConfig({
    plugins: [
        laravel({
            // ...
            transformOnServe: (code, devServerUrl) => code.replaceAll('/@imagetools', devServerUrl+'/@imagetools'),
        }),
        imagetools(),
    ],
});

現在,在 Vite 提供資源服務時,它將輸出指向 Vite 開發伺服器的 URL:

<img src="http://[::1]:5173/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520">