跳转至内容

资源打包 (Vite)

简介

Vite 是一款现代前端构建工具,它提供了极快的开发环境,并将您的代码打包以供生产使用。在构建 Laravel 应用程序时,您通常会使用 Vite 将应用程序的 CSS 和 JavaScript 文件打包成生产环境就绪的资源。

Laravel 通过提供官方插件和 Blade 指令,实现与 Vite 的无缝集成,从而加载用于开发和生产环境的资源。

安装与设置

以下文档介绍了如何手动安装和配置 Laravel Vite 插件。不过,Laravel 的 入门套件 (Starter Kits) 已经包含了所有这些基础架构,是开始使用 Laravel 和 Vite 最快捷的方式。

安装 Node

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

1node -v
2npm -v

您可以直接从 Node 官网 下载图形化安装程序,轻松安装最新版本的 Node 和 NPM。或者,如果您正在使用 Laravel Sail,则可以通过 Sail 调用 Node 和 NPM。

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

安装 Vite 和 Laravel 插件

在全新的 Laravel 安装中,您会在应用程序目录结构的根目录下找到一个 package.json 文件。默认的 package.json 文件已经包含了使用 Vite 和 Laravel 插件所需的一切。您可以通过 NPM 安装应用程序的前端依赖项:

1npm install

配置 Vite

Vite 通过项目根目录下的 vite.config.js 文件进行配置。您可以根据需要自定义此文件,也可以安装应用程序所需的任何其他插件,例如 @vitejs/plugin-react@sveltejs/vite-plugin-svelte@vitejs/plugin-vue

Laravel Vite 插件要求您指定应用程序的入口点。这些可以是 JavaScript 或 CSS 文件,也包含预处理语言,如 TypeScript、JSX、TSX 和 Sass。

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel([
7 'resources/css/app.css',
8 'resources/js/app.js',
9 ]),
10 ],
11});

如果您正在构建 SPA(单页应用,包括使用 Inertia 构建的应用),Vite 在没有 CSS 入口点的情况下效果最好。

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel([
7 'resources/css/app.css',
8 'resources/js/app.js',
9 ]),
10 ],
11});

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

1import './bootstrap';
2import '../css/app.css';

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

使用安全的开发服务器

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

如果您正在使用 Laravel Herd 并已保护了站点,或者您正在使用 Laravel Valet 并已对您的应用程序运行了 secure 命令,Laravel Vite 插件将自动检测并为您使用生成的 TLS 证书。

如果您使用不匹配应用程序目录名称的主机保护了站点,则可以在应用程序的 vite.config.js 文件中手动指定主机。

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 // ...
8 detectTls: 'my-app.test',
9 }),
10 ],
11});

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

1// ...
2import fs from 'fs';
3 
4const host = 'my-app.test';
5 
6export default defineConfig({
7 // ...
8 server: {
9 host,
10 hmr: { host },
11 https: {
12 key: fs.readFileSync(`/path/to/${host}.key`),
13 cert: fs.readFileSync(`/path/to/${host}.crt`),
14 },
15 },
16});

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

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

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

1// ...
2 
3export default defineConfig({
4 // ...
5 server: {
6 hmr: {
7 host: 'localhost',
8 },
9 },
10});

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

加载脚本和样式

配置好 Vite 入口点后,您现在可以在应用程序根模板的 <head> 中添加 @vite() Blade 指令来引用它们:

1<!DOCTYPE html>
2<head>
3 {{-- ... --}}
4 
5 @vite(['resources/css/app.css', 'resources/js/app.js'])
6</head>

如果您是通过 JavaScript 导入 CSS,则只需要包含 JavaScript 入口点。

1<!DOCTYPE html>
2<head>
3 {{-- ... --}}
4 
5 @vite('resources/js/app.js')
6</head>

@vite 指令将自动检测 Vite 开发服务器并注入 Vite 客户端以启用热模块替换 (HMR)。在构建模式下,该指令将加载已编译和版本化的资源,包括任何已导入的 CSS。

如果需要,您也可以在调用 @vite 指令时指定已编译资源的构建路径:

1<!doctype html>
2<head>
3 {{-- Given build path is relative to public path. --}}
4 
5 @vite('resources/js/app.js', 'vendor/courier/build')
6</head>

内联资源 (Inline Assets)

有时可能需要包含资源的原始内容,而不是链接到资源的版本化 URL。例如,当向 PDF 生成器传递 HTML 内容时,可能需要直接在页面中包含资源内容。您可以使用 Vite facade 提供的 content 方法输出 Vite 资源的内容:

1@use('Illuminate\Support\Facades\Vite')
2 
3<!doctype html>
4<head>
5 {{-- ... --}}
6 
7 <style>
8 {!! Vite::content('resources/css/app.css') !!}
9 </style>
10 <script>
11 {!! Vite::content('resources/js/app.js') !!}
12 </script>
13</head>

运行 Vite

运行 Vite 有两种方式。您可以通过 dev 命令运行开发服务器,这在本地开发时非常有用。开发服务器会自动检测文件更改,并立即反映在任何打开的浏览器窗口中。

或者,运行 build 命令将对应用程序的资源进行版本控制和打包,并为部署到生产环境做好准备。

1# Run the Vite development server...
2npm run dev
3 
4# Build and version the assets for production...
5npm run build

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

使用 JavaScript

别名 (Aliases)

默认情况下,Laravel 插件提供了一个通用的别名,以帮助您快速上手并方便地导入应用程序资源:

1{
2 '@' => '/resources/js'
3}

您可以将自己的别名添加到 vite.config.js 配置文件中,从而覆盖 '@' 别名:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel(['resources/ts/app.tsx']),
7 ],
8 resolve: {
9 alias: {
10 '@': '/resources/ts',
11 },
12 },
13});

Vue

如果您想使用 Vue 框架构建前端,那么您还需要安装 @vitejs/plugin-vue 插件:

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

然后,您可以将该插件包含在 vite.config.js 配置文件中。在 Laravel 中使用 Vue 插件时,还有一些额外的选项需要注意。

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3import vue from '@vitejs/plugin-vue';
4 
5export default defineConfig({
6 plugins: [
7 laravel(['resources/js/app.js']),
8 vue({
9 template: {
10 transformAssetUrls: {
11 // The Vue plugin will re-write asset URLs, when referenced
12 // in Single File Components, to point to the Laravel web
13 // server. Setting this to `null` allows the Laravel plugin
14 // to instead re-write asset URLs to point to the Vite
15 // server instead.
16 base: null,
17 
18 // The Vue plugin will parse absolute URLs and treat them
19 // as absolute paths to files on disk. Setting this to
20 // `false` will leave absolute URLs un-touched so they can
21 // reference assets in the public directory as expected.
22 includeAbsolute: false,
23 },
24 },
25 }),
26 ],
27});

Laravel 的 入门套件 已经包含了正确的 Laravel、Vue 和 Vite 配置。这些入门套件是开始使用 Laravel、Vue 和 Vite 最快捷的方式。

React

如果您想使用 React 框架构建前端,那么您还需要安装 @vitejs/plugin-react 插件:

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

然后,您可以将该插件包含在 vite.config.js 配置文件中。

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3import react from '@vitejs/plugin-react';
4 
5export default defineConfig({
6 plugins: [
7 laravel(['resources/js/app.jsx']),
8 react(),
9 ],
10});

您需要确保任何包含 JSX 的文件都具有 .jsx.tsx 扩展名,并记住按需更新您的入口点,如上文所示

您还需要在现有的 @vite 指令旁边包含额外的 @viteReactRefresh Blade 指令。

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

@viteReactRefresh 指令必须在 @vite 指令之前调用。

Laravel 的 入门套件 已经包含了正确的 Laravel、React 和 Vite 配置。这些入门套件是开始使用 Laravel、React 和 Vite 最快捷的方式。

Svelte

如果您想使用 Svelte 框架构建前端,那么您还需要安装 @sveltejs/vite-plugin-svelte 插件:

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

然后,您可以将该插件包含在 vite.config.js 配置文件中。

1import { svelte } from '@sveltejs/vite-plugin-svelte';
2import laravel from 'laravel-vite-plugin';
3import { defineConfig } from 'vite';
4 
5export default defineConfig({
6 plugins: [
7 laravel({
8 input: ['resources/js/app.ts'],
9 ssr: 'resources/js/ssr.ts',
10 refresh: true,
11 }),
12 svelte(),
13 ],
14});

Laravel 的 入门套件 已经包含了正确的 Laravel、Svelte 和 Vite 配置。这些入门套件是开始使用 Laravel、Svelte 和 Vite 最快捷的方式。

Inertia

Laravel Vite 插件提供了一个便捷的 resolvePageComponent 函数,以帮助您解析 Inertia 页面组件。以下是该辅助函数在 Vue 3 中使用的示例;不过,您也可以在 React 或 Svelte 等其他框架中使用该函数:

1import { createApp, h } from 'vue';
2import { createInertiaApp } from '@inertiajs/vue3';
3import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
4 
5createInertiaApp({
6 resolve: (name) => resolvePageComponent(`./Pages/${name}.vue`, import.meta.glob('./Pages/**/*.vue')),
7 setup({ el, App, props, plugin }) {
8 createApp({ render: () => h(App, props) })
9 .use(plugin)
10 .mount(el)
11 },
12});

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

Laravel 的 入门套件 已经包含了正确的 Laravel、Inertia 和 Vite 配置。这些入门套件是开始使用 Laravel、Inertia 和 Vite 最快捷的方式。

URL 处理

当在 HTML、CSS 或 JS 中使用 Vite 引用资源时,需要注意一些注意事项。首先,如果您使用绝对路径引用资源,Vite 将不会把该资源包含在构建中;因此,您应该确保资源在您的公共目录(public)中可用。使用 专门的 CSS 入口点 时,应避免使用绝对路径,因为在开发过程中,浏览器会尝试从 Vite 开发服务器加载这些路径,而不是从您的公共目录加载。

引用相对资源路径时,请记住这些路径是相对于引用它们的文件而言的。任何通过相对路径引用的资源都将被 Vite 重写、版本化和打包。

考虑以下项目结构:

1public/
2 taylor.png
3resources/
4 js/
5 Pages/
6 Welcome.vue
7 images/
8 abigail.png

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

1<!-- This asset is not handled by Vite and will not be included in the build -->
2<img src="/taylor.png">
3 
4<!-- This asset will be re-written, versioned, and bundled by Vite -->
5<img src="../../images/abigail.png">

使用样式表

Laravel 的 入门套件 已经包含了正确的 Tailwind 和 Vite 配置。或者,如果您想在不使用入门套件的情况下将 Tailwind 与 Laravel 一起使用,请查看 Tailwind 的 Laravel 安装指南

所有 Laravel 应用程序都已经包含了 Tailwind 和配置正确的 vite.config.js 文件。因此,您只需要启动 Vite 开发服务器或运行 dev Composer 命令,它将同时启动 Laravel 和 Vite 开发服务器:

1composer run dev

应用程序的 CSS 可以放在 resources/css/app.css 文件中。

使用 Blade 和路由

使用 Vite 处理静态资源

在 JavaScript 或 CSS 中引用资源时,Vite 会自动处理并对其进行版本控制。此外,在构建基于 Blade 的应用程序时,Vite 还可以处理并版本化您仅在 Blade 模板中引用的静态资源。

然而,为了实现这一点,您需要在插件的 assets 选项中指定资源,从而让 Vite 知晓它们。例如,如果您想处理并版本化存储在 resources/images 中的所有图片以及 resources/fonts 中的所有字体,您应该将以下内容添加到您的 Vite 配置中:

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

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

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

在 Laravel Vite 插件 3.0 版本之前,必须使用 import.meta.glob 在应用程序的入口点导入静态资源。assets 选项是由于 Vite 8 的变更而引入的。

保存时自动刷新

当您的应用程序使用传统的 Blade 服务器端渲染构建时,Vite 可以通过在您更改应用程序中的视图文件时自动刷新浏览器,从而改进您的开发工作流程。要开始使用,您只需将 refresh 选项设置为 true 即可。

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 // ...
8 refresh: true,
9 }),
10 ],
11});

refresh 选项为 true 时,保存以下目录中的文件将在您运行 npm run dev 时触发浏览器执行全页面刷新:

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

如果您正在利用 Ziggy 在应用程序前端生成路由链接,监控 routes/** 目录非常有用。

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

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 // ...
8 refresh: ['resources/views/**'],
9 }),
10 ],
11});

在底层,Laravel Vite 插件使用了 vite-plugin-full-reload 包,它提供了一些高级配置选项来微调此功能的行为。如果您需要这种级别的自定义,可以提供 config 定义:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 // ...
8 refresh: [{
9 paths: ['path/to/watch/**'],
10 config: { delay: 300 }
11 }],
12 }),
13 ],
14});

别名 (Aliases)

在 JavaScript 应用程序中,创建别名以指向经常引用的目录是很常见的。但是,您也可以使用 Illuminate\Support\Facades\Vite 类上的 macro 方法创建在 Blade 中使用的别名。通常,“宏”应该在服务提供者boot 方法中定义:

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

一旦定义了宏,就可以在模板中调用它。例如,我们可以使用上面定义的 image 宏来引用位于 resources/images/logo.png 的资源:

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

资源预取

在使用 Vite 的代码分割功能构建 SPA 时,所需的资源会在每次页面导航时获取。这种行为可能导致 UI 渲染延迟。如果这对您选择的前端框架是个问题,Laravel 提供了在初始页面加载时主动预取应用程序 JavaScript 和 CSS 资源的功能。

您可以通过在服务提供者boot 方法中调用 Vite::prefetch 方法,来指示 Laravel 主动预取您的资源:

1<?php
2 
3namespace App\Providers;
4 
5use Illuminate\Support\Facades\Vite;
6use Illuminate\Support\ServiceProvider;
7 
8class AppServiceProvider extends ServiceProvider
9{
10 /**
11 * Register any application services.
12 */
13 public function register(): void
14 {
15 // ...
16 }
17 
18 /**
19 * Bootstrap any application services.
20 */
21 public function boot(): void
22 {
23 Vite::prefetch(concurrency: 3);
24 }
25}

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

1/**
2 * Bootstrap any application services.
3 */
4public function boot(): void
5{
6 Vite::prefetch();
7}

默认情况下,预取将在页面 load 事件触发时开始。如果您想自定义预取开始的时间,可以指定一个 Vite 将要监听的事件:

1/**
2 * Bootstrap any application services.
3 */
4public function boot(): void
5{
6 Vite::prefetch(event: 'vite:prefetch');
7}

使用上面的代码,当您手动在 window 对象上分派 vite:prefetch 事件时,预取就会开始。例如,您可以让预取在页面加载三秒后开始:

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

自定义基础 URL

如果您的 Vite 编译资源部署到与应用程序不同的域(例如通过 CDN),则必须在应用程序的 .env 文件中指定 ASSET_URL 环境变量:

1ASSET_URL=https://cdn.example.com

配置资源 URL 后,所有指向您资源的重写 URL 都将以配置的值作为前缀:

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

请记住,绝对 URL 不会被 Vite 重写,因此它们不会被添加前缀。

环境变量

您可以通过在应用程序的 .env 文件中为环境变量添加 VITE_ 前缀,将它们注入到 JavaScript 中:

1VITE_SENTRY_DSN_PUBLIC=http://example.com

您可以通过 import.meta.env 对象访问注入的环境变量:

1import.meta.env.VITE_SENTRY_DSN_PUBLIC

在测试中禁用 Vite

Laravel 的 Vite 集成会尝试在运行测试时解析您的资源,这要求您要么运行 Vite 开发服务器,要么构建您的资源。

如果您希望在测试期间模拟 Vite,可以调用 withoutVite 方法,该方法适用于任何扩展了 Laravel TestCase 类的测试:

1test('without vite example', function () {
2 $this->withoutVite();
3 
4 // ...
5});
1use Tests\TestCase;
2 
3class ExampleTest extends TestCase
4{
5 public function test_without_vite_example(): void
6 {
7 $this->withoutVite();
8 
9 // ...
10 }
11}

如果您想对所有测试禁用 Vite,可以从基础 TestCase 类的 setUp 方法中调用 withoutVite 方法:

1<?php
2 
3namespace Tests;
4 
5use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
6 
7abstract class TestCase extends BaseTestCase
8{
9 protected function setUp(): void
10 {
11 parent::setUp();
12 
13 $this->withoutVite();
14 }
15}

服务器端渲染 (SSR)

Laravel Vite 插件使得使用 Vite 设置服务器端渲染变得轻而易举。要开始使用,请在 resources/js/ssr.js 创建一个 SSR 入口点,并通过将配置选项传递给 Laravel 插件来指定该入口点:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 input: 'resources/js/app.js',
8 ssr: 'resources/js/ssr.js',
9 }),
10 ],
11});

为确保您不会忘记重建 SSR 入口点,我们建议增强应用程序 package.json 中的“build”脚本以创建您的 SSR 构建:

1"scripts": {
2 "dev": "vite",
3 "build": "vite build"
4 "build": "vite build && vite build --ssr"
5}

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

1npm run build
2node bootstrap/ssr/ssr.js

如果您正在使用 Inertia 的 SSR,则可以使用 inertia:start-ssr Artisan 命令来启动 SSR 服务器:

1php artisan inertia:start-ssr

Laravel 的 入门套件 已经包含了正确的 Laravel、Inertia SSR 和 Vite 配置。这些入门套件是开始使用 Laravel、Inertia SSR 和 Vite 最快捷的方式。

脚本和样式标签属性

内容安全策略 (CSP) Nonce

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

1<?php
2 
3namespace App\Http\Middleware;
4 
5use Closure;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Vite;
8use Symfony\Component\HttpFoundation\Response;
9 
10class AddContentSecurityPolicyHeaders
11{
12 /**
13 * Handle an incoming request.
14 *
15 * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
16 */
17 public function handle(Request $request, Closure $next): Response
18 {
19 Vite::useCspNonce();
20 
21 return $next($request)->withHeaders([
22 'Content-Security-Policy' => "script-src 'nonce-".Vite::cspNonce()."'",
23 ]);
24 }
25}

调用 useCspNonce 方法后,Laravel 将自动在所有生成的脚本和样式标签上包含 nonce 属性。

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

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

如果您已经有一个想要指示 Laravel 使用的 nonce,则可以将该 nonce 传递给 useCspNonce 方法:

1Vite::useCspNonce($nonce);

子资源完整性 (SRI)

如果您的 Vite 清单包含资源的 integrity 哈希值,Laravel 将自动在它生成的任何脚本和样式标签上添加 integrity 属性,以强制执行子资源完整性。默认情况下,Vite 不会在其清单中包含 integrity 哈希值,但您可以通过安装 vite-plugin-manifest-sri NPM 插件来启用它。

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

然后,您可以在 vite.config.js 文件中启用此插件:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3import manifestSRI from 'vite-plugin-manifest-sri';
4 
5export default defineConfig({
6 plugins: [
7 laravel({
8 // ...
9 }),
10 manifestSRI(),
11 ],
12});

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

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

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

1Vite::useIntegrityKey(false);

任意属性

如果您需要在脚本和样式标签上包含额外的属性,例如 data-turbo-track 属性,可以通过 useScriptTagAttributesuseStyleTagAttributes 方法指定它们。通常,这些方法应该从服务提供者中调用:

1use Illuminate\Support\Facades\Vite;
2 
3Vite::useScriptTagAttributes([
4 'data-turbo-track' => 'reload', // Specify a value for the attribute...
5 'async' => true, // Specify an attribute without a value...
6 'integrity' => false, // Exclude an attribute that would otherwise be included...
7]);
8 
9Vite::useStyleTagAttributes([
10 'data-turbo-track' => 'reload',
11]);

如果您需要有条件地添加属性,可以传递一个回调函数,该回调函数将接收资源源路径、其 URL、其清单块 (manifest chunk) 和整个清单:

1use Illuminate\Support\Facades\Vite;
2 
3Vite::useScriptTagAttributes(fn (string $src, string $url, array|null $chunk, array|null $manifest) => [
4 'data-turbo-track' => $src === 'resources/js/app.js' ? 'reload' : false,
5]);
6 
7Vite::useStyleTagAttributes(fn (string $src, string $url, array|null $chunk, array|null $manifest) => [
8 'data-turbo-track' => $chunk && $chunk['isEntry'] ? 'reload' : false,
9]);

当 Vite 开发服务器运行时,$chunk$manifest 参数将为 null

高级自定义

开箱即用,Laravel 的 Vite 插件使用了合理的约定,应该适用于大多数应用程序;然而,有时您可能需要自定义 Vite 的行为。为了启用额外的自定义选项,我们提供了以下方法和选项,它们可以替代 @vite Blade 指令使用:

1<!doctype html>
2<head>
3 {{-- ... --}}
4 
5 {{
6 Vite::useHotFile(storage_path('vite.hot')) // Customize the "hot" file...
7 ->useBuildDirectory('bundle') // Customize the build directory...
8 ->useManifestFilename('assets.json') // Customize the manifest filename...
9 ->withEntryPoints(['resources/js/app.js']) // Specify the entry points...
10 ->createAssetPathsUsing(function (string $path, ?bool $secure) { // Customize the backend path generation for built assets...
11 return "https://cdn.example.com/{$path}";
12 })
13 }}
14</head>

vite.config.js 文件中,您应该指定相同的配置:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 hotFile: 'storage/vite.hot', // Customize the "hot" file...
8 buildDirectory: 'bundle', // Customize the build directory...
9 input: ['resources/js/app.js'], // Specify the entry points...
10 }),
11 ],
12 build: {
13 manifest: 'assets.json', // Customize the manifest filename...
14 },
15});

开发服务器跨域资源共享 (CORS)

如果您在浏览器中从 Vite 开发服务器获取资源时遇到跨域资源共享 (CORS) 问题,则可能需要授予您的自定义源访问开发服务器的权限。Vite 结合 Laravel 插件无需额外配置即可允许以下源:

  • ::1
  • 127.0.0.1
  • localhost
  • *.test
  • *.localhost
  • 项目 .env 中的 APP_URL

为项目允许自定义源的最简单方法是确保应用程序的 APP_URL 环境变量与您在浏览器中访问的源匹配。例如,如果您访问 https://my-app.laravel,则应更新您的 .env 以匹配:

1APP_URL=https://my-app.laravel

如果您需要对源进行更细粒度的控制(例如支持多个源),则应利用 Vite 全面且灵活的内置 CORS 服务器配置。例如,您可以在项目的 vite.config.js 文件中的 server.cors.origin 配置选项中指定多个源:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 input: 'resources/js/app.js',
8 refresh: true,
9 }),
10 ],
11 server: {
12 cors: {
13 origin: [
14 'https://backend.laravel',
15 'http://admin.laravel:8566',
16 ],
17 },
18 },
19});

您还可以包含正则表达式模式,如果您想允许给定顶级域(如 *.laravel)的所有源,这将很有帮助:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3 
4export default defineConfig({
5 plugins: [
6 laravel({
7 input: 'resources/js/app.js',
8 refresh: true,
9 }),
10 ],
11 server: {
12 cors: {
13 origin: [
14 // Supports: SCHEME://DOMAIN.laravel[:PORT]
15 /^https?:\/\/.*\.laravel(:\d+)?$/,
16 ],
17 },
18 },
19});

修正开发服务器 URL

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

例如,当 Vite 正在为您提供资源时,vite-imagetools 插件会输出如下 URL:

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

vite-imagetools 插件期望输出的 URL 将被 Vite 拦截,然后该插件可以处理所有以 /@imagetools 开头的 URL。如果您使用的插件预料到这种行为,则需要手动修正 URL。您可以通过在 vite.config.js 文件中使用 transformOnServe 选项来完成此操作。

在这个特定示例中,我们将开发服务器 URL 添加到生成代码中所有 /@imagetools 出现的位置之前:

1import { defineConfig } from 'vite';
2import laravel from 'laravel-vite-plugin';
3import { imagetools } from 'vite-imagetools';
4 
5export default defineConfig({
6 plugins: [
7 laravel({
8 // ...
9 transformOnServe: (code, devServerUrl) => code.replaceAll('/@imagetools', devServerUrl+'/@imagetools'),
10 }),
11 imagetools(),
12 ],
13});

现在,当 Vite 提供资源时,它将输出指向 Vite 开发服务器的 URL:

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