laravel
4. 基础知识
资源打包(Vite)

介绍

Vite (opens in a new tab) 是一个现代化的前端构建工具,它提供了极快的开发环境,并为生产环境打包您的代码。在使用 Laravel 构建应用程序时,您通常会使用 Vite 将应用程序的 CSS 和 JavaScript 文件打包为可用于生产的资源。

Laravel 通过提供官方插件和 Blade 指令与 Vite 无缝集成,以便在开发和生产环境中加载您的资源。

[!注意]
您是否正在运行 Laravel Mix?在新的 Laravel 安装中,Vite 已取代 Laravel Mix。有关 Mix 的文档,请访问Laravel Mix (opens in a new tab)网站。如果您想切换到 Vite,请参阅我们的[迁移指南](https://github.com/laravel/vite-plugin/blob/main/UPGRADE.md#从 (opens in a new tab) Laravel-Mix 迁移到 Vite)。

在 Vite 和 Laravel Mix 之间选择

在过渡到 Vite 之前,新的 Laravel 应用程序在打包资源时使用了Mix (opens in a new tab),它由webpack (opens in a new tab)提供支持。Vite 专注于在构建丰富的 JavaScript 应用程序时提供更快、更高效的体验。如果您正在开发单页应用程序(SPA),包括使用Inertia (opens in a new tab)等工具开发的应用程序,Vite 将是完美的选择。

Vite 也适用于具有 JavaScript“点缀”的传统服务器端渲染应用程序,包括使用Livewire (opens in a new tab)的应用程序。然而,它缺少 Laravel Mix 支持的一些功能,例如将未在 JavaScript 应用程序中直接引用的任意资产复制到构建中的能力。

迁移回 Mix

您是否使用我们的 Vite 脚手架启动了一个新的 Laravel 应用程序,但需要迁移回 Laravel Mix 和 webpack?没问题。请参考我们的[从 Vite 迁移到 Mix 的官方指南](https://github.com/laravel/vite-plugin/blob/main/UPGRADE.md#从 (opens in a new tab) Vite 迁移到 Laravel-Mix)。

安装与设置

[!注意]
以下文档讨论了如何手动安装和配置 Laravel Vite 插件。然而,Laravel 的入门套件已经包含了所有这些脚手架,是开始使用 Laravel 和 Vite 的最快方法。

安装 Node

在运行 Vite 和 Laravel 插件之前,您必须确保已安装 Node.js(16+)和 NPM:

node -v
npm -v

您可以使用官方 Node 网站 (opens in a new tab)上的简单图形安装程序轻松安装最新版本的 Node 和 NPM。或者,如果您使用Laravel Sail (opens in a new tab),您可以通过 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-vue@vitejs/plugin-react

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! 移除]
            'resources/js/app.js',
        ]),
    ],
});

相反,您应该通过 JavaScript 导入您的 CSS。通常,这将在应用程序的resources/js/app.js文件中完成:

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

Laravel 插件还支持多个入口点和高级配置选项,例如SSR 入口点

使用安全开发服务器

如果您的本地开发 Web 服务器通过 HTTPS 为您的应用程序提供服务,您可能会在连接到 Vite 开发服务器时遇到问题。

如果您使用Laravel Herd (opens in a new tab)并已保护站点,或者您使用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! 添加]
        }),
    ],
});

当使用其他 Web 服务器时,您应该生成受信任的证书并手动配置 Vite 使用生成的证书:

//...
import fs from 'fs'; // [tl! 添加]
 
const host = 'my-app.test'; // [tl! 添加]
 
export default defineConfig({
    //...
    server: { // [tl! 添加]
        host, // [tl! 添加]
        hmr: { host }, // [tl! 添加]
        https: { // [tl! 添加]
            key: fs.readFileSync(`/path/to/${host}.key`), // [tl! 添加]
            cert: fs.readFileSync(`/path/to/${host}.crt`), // [tl! 添加]
        }, // [tl! 添加]
    }, // [tl! 添加]
});

如果您无法为您的系统生成受信任的证书,您可以安装并配置@vitejs/plugin-basic-ssl插件 (opens in a new tab)。当使用不受信任的证书时,您需要在运行npm run dev命令时,在浏览器中通过控制台中的“Local”链接接受 Vite 开发服务器的证书警告。

在 WSL2 上的 Sail 中运行开发服务器

在 Windows Subsystem for Linux 2(WSL2)上的Laravel Sail中运行 Vite 开发服务器时,您应该将以下配置添加到vite.config.js文件中,以确保浏览器可以与开发服务器进行通信:

//...
 
export default defineConfig({
    //...
    server: { // [tl! 添加:开始]
        hmr: {
            host: 'localhost',
        },
    }, // [tl! 添加:结束]
});

如果在开发服务器运行时,浏览器中未反映文件更改,您可能还需要配置 Vite 的server.watch.usePolling选项 (opens in a new tab)

加载您的脚本和样式

配置好 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>
    {{-- 给定的构建路径是相对于公共路径的。 --}}
 
    @vite('resources/js/app.js', 'vendor/courier/build')
</head>

内联资源

有时可能需要包含资源的原始内容,而不是链接到资源的版本化 URL。例如,当将 HTML 内容传递给 PDF 生成器时,您可能需要将资产内容直接包含在页面中。您可以使用Vite外观提供的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命令将为您的应用程序的资源进行版本化和打包,并为您将其部署到生产环境做好准备:

# 运行 Vite 开发服务器...
npm run dev
 
# 为生产环境构建和版本化资源...
npm run build

如果您在 WSL2 上的Sail中运行开发服务器,您可能需要一些[额外的配置](#在 Sail 中配置 WSL2 上的 HMR)选项。

使用 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 (opens in a new tab) 框架构建前端,那么您还需要安装 @vitejs/plugin-vue 插件:

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

然后,您可以在 vite.config.js 配置文件中包含该插件。在将 Vue 插件与 Laravel 一起使用时,您还需要一些其他选项:

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: {
                    // Vue 插件在引用单文件组件中的资源 URL 时会重写这些 URL,使其指向 Laravel Web 服务器。将此设置为 `null` 可让 Laravel 插件将资源 URL 重写为指向 Vite 服务器。
                    base: null,
 
                    // Vue 插件会解析绝对 URL,并将它们视为磁盘上文件的绝对路径。将此设置为 `false` 将使绝对 URL 保持不变,以便它们可以按预期引用公共目录中的资产。
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

[!NOTE]
Laravel 的入门套件已经包含了适当的 Laravel、Vue 和 Vite 配置。查看Laravel Breeze,以最快的方式开始使用 Laravel、Vue 和 Vite。

React

如果您希望使用 React (opens in a new tab) 框架构建前端,那么您还需要安装 @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 Breeze,以最快的方式开始使用 Laravel、React 和 Vite。

Inertia

Laravel Vite 插件提供了一个方便的 resolvePageComponent 函数,以帮助您解析您的 Inertia 页面组件。以下是在 Vue 3 中使用该助手的示例;但是,您也可以在其他框架(如 React)中使用该函数:

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 }) {
    return createApp({ render: () => h(App, props) })
     .use(plugin)
     .mount(el)
  },
});

如果您在使用 Inertia 时使用 Vite 的代码分割功能,我们建议配置资产预取

[!NOTE]
Laravel 的入门套件已经包含了适当的 Laravel、Inertia 和 Vite 配置。查看Laravel Breeze,以最快的方式开始使用 Laravel、Inertia 和 Vite。

URL 处理

在使用 Vite 并在应用程序的 HTML、CSS 或 JS 中引用资产时,有几个需要注意的地方。首先,如果您使用绝对路径引用资产,Vite 将不会在构建中包含该资产;因此,您应该确保该资产在您的公共目录中可用。当使用专用的 CSS 入口点时,您应该避免使用绝对路径,因为在开发过程中,浏览器将尝试从托管 CSS 的 Vite 开发服务器而不是从您的公共目录加载这些路径。

当引用相对资产路径时,您应该记住,这些路径是相对于引用它们的文件的。通过相对路径引用的任何资产都将由 Vite 重写、版本化和捆绑。

考虑以下项目结构:

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

以下示例演示了 Vite 将如何处理相对和绝对 URL:

<!-- 此资产不由 Vite 处理,不会包含在构建中 -->
<img src="/taylor.png">
 
<!-- 此资产将由 Vite 重写、版本化和捆绑 -->
<img src="../../images/abigail.png">

使用样式表

您可以在 Vite 文档 (opens in a new tab)中了解更多关于 Vite 的 CSS 支持。如果您使用诸如 Tailwind (opens in a new tab) 之类的 PostCSS 插件,您可以在项目的根目录中创建一个 postcss.config.js 文件,Vite 将自动应用它:

export default {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    },
};

[!NOTE]
Laravel 的入门套件已经包含了适当的 Tailwind、PostCSS 和 Vite 配置。或者,如果您想在不使用我们的入门套件的情况下使用 Tailwind 和 Laravel,请查看 Tailwind 针对 Laravel 的安装指南 (opens in a new tab)

使用 Blade 和路由

使用 Vite 处理静态资产

在您的 JavaScript 或 CSS 中引用资产时,Vite 会自动处理并为其添加版本。此外,在构建基于 Blade 的应用程序时,Vite 还可以处理并为您仅在 Blade 模板中引用的静态资产添加版本。

但是,为了实现这一点,您需要通过将静态资产导入到应用程序的入口点来让 Vite 知道您的资产。例如,如果您要处理并为存储在 resources/images 中的所有图像和存储在 resources/fonts 中的所有字体添加版本,您应该在应用程序的 resources/js/app.js 入口点中添加以下内容:

import.meta.glob([
  '../images/**',
  '../fonts/**',
]);

现在,在运行 npm run build 时,Vite 将处理这些资产。然后,您可以在 Blade 模板中使用 Vite::asset 方法引用这些资产,该方法将为给定的资产返回添加版本的 URL:

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

保存时刷新

当您的应用程序使用传统的服务器端渲染与 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/**

如果您在应用程序的前端使用 Ziggy (opens in a new tab) 生成路由链接,那么监视 routes/** 目录是很有用的。

如果这些默认路径不符合您的需求,您可以指定自己要监视的路径列表:

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

在底层,Laravel Vite 插件使用 vite-plugin-full-reload (opens in a new tab) 包,该包提供了一些高级配置选项来微调此功能的行为。如果您需要这种级别的自定义,您可以提供一个 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 方法中定义:

/**
 * 引导任何应用程序服务。
 */
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
{
    /**
     * 注册任何应用程序服务。
     */
    public function register(): void
    {
        //...
    }
 
    /**
     * 引导任何应用程序服务。
     */
    public function boot(): void
    {
        Vite::prefetch(concurrency: 3);
    }
}

在上面的示例中,在每个页面加载时,资产将以最多 3 个并发下载进行预取。您可以根据应用程序的需要修改并发数,或者如果应用程序应一次下载所有资产,则可以指定无并发限制:

/**
 * 引导任何应用程序服务。
 */
public function boot(): void
{
    Vite::prefetch();
}

默认情况下,预取将在 页面 加载 事件 (opens in a new tab)触发时开始。如果您想自定义预取开始的时间,您可以指定一个 Vite 将监听的事件:

/**
 * 引导任何应用程序服务。
 */
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 类的测试:

test('without vite example', function () {
    $this->withoutVite();
 
    //...
});
use Tests\TestCase;
 
class ExampleTest extends 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// [tl! add:start]
    {
        parent::setUp();
 
        $this->withoutVite();
    }// [tl! add:end]
}

服务器端渲染(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" // [tl! remove]
     "build": "vite build && vite build --ssr" // [tl! add]
}

然后,要构建并启动 SSR 服务器,您可以运行以下命令:

npm run build
node bootstrap/ssr/ssr.js

如果您正在使用 带有 Inertia 的 SSR (opens in a new tab),您可以使用 inertia:start-ssr Artisan 命令来启动 SSR 服务器:

php artisan inertia:start-ssr

[!NOTE]
Laravel 的入门套件已经包含了适当的 Laravel、Inertia SSR 和 Vite 配置。查看Laravel Breeze,以最快的方式开始使用 Laravel、Inertia SSR 和 Vite。

脚本和样式标签属性

内容安全策略(CSP)随机数

如果您希望在脚本和样式标签上包含一个nonce 属性 (opens in a new tab)作为内容安全策略 (opens in a new tab)的一部分,您可以在自定义中间件中使用 useCspNonce 方法生成或指定一个随机数:

<?php
 
namespace App\Http\Middleware;
 
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Vite;
use Symfony\Component\HttpFoundation\Response;
 
class AddContentSecurityPolicyHeaders
{
    /**
     * 处理传入的请求。
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    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 属性。

如果您需要在其他地方指定随机数,包括与 Laravel 的入门套件一起包含的 Ziggy @route 指令](https://github.com/tighten/ziggy#using-routes-with-a-content-security-policy),您可以使用 (opens in a new tab) cspNonce 方法获取它:

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

如果您已经有一个希望指示 Laravel 使用的随机数,可以将随机数传递给 useCspNonce 方法:

Vite::useCspNonce($nonce);

子资源完整性(SRI)

如果您的 Vite 清单包含资产的 integrity 哈希值,Laravel 将自动在其生成的任何脚本和样式标签上添加 integrity 属性,以强制实施子资源完整性 (opens in a new tab)。默认情况下,Vite 在其清单中不包含 integrity 哈希值,但您可以通过安装 vite-plugin-manifest-sri (opens in a new tab) 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';// [tl! add]
 
export default defineConfig({
    plugins: [
        laravel({
            //...
        }),
        manifestSRI(),// [tl! add]
    ],
});

如果需要,您还可以自定义可以找到完整性哈希值的清单键:

use Illuminate\Support\Facades\Vite;
 
Vite::useIntegrityKey('custom-integrity-key');

如果您希望完全禁用此自动检测,可以将 false 传递给 useIntegrityKey 方法:

Vite::useIntegrityKey(false);

任意属性

如果您需要在脚本和样式标签上包含其他属性,例如 data-turbo-track (opens in a new tab) 属性,您可以通过 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')) // 自定义 "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', // 自定义 "hot" 文件...
            buildDirectory: 'bundle', // 自定义构建目录...
            input: ['resources/js/app.js'], // 指定入口点...
        }),
    ],
    build: {
      manifest: 'assets.json', // 自定义清单文件名...
    },
});

纠正开发服务器 URL

Vite 生态系统中的一些插件假定以正斜杠开头的 URL 始终指向 Vite 开发服务器。然而,由于 Laravel 集成的性质,情况并非如此。

例如,当 Vite 为您的资产提供服务时,vite-imagetools 插件会输出如下 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="/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520"><!-- [tl! remove] -->
+ <img src="http://[::1]:5173/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520"><!-- [tl! add] -->