跳到内容

资源打包 (Vite)

简介

Vite 是一个现代化的前端构建工具,提供极快的开发环境,并将你的代码打包用于生产环境。当使用 Laravel 构建应用时,你通常会使用 Vite 将应用的 CSS 和 JavaScript 文件打包成可用于生产环境的资源。

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

你是否正在运行 Laravel Mix?Vite 已经取代了新 Laravel 安装中的 Laravel Mix。有关 Mix 的文档,请访问 Laravel Mix 网站。如果你想切换到 Vite,请查看我们的 迁移指南

Vite 和 Laravel Mix 之间的选择

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

Vite 也适用于传统的服务端渲染应用,这些应用带有 "sprinkles" JavaScript,包括那些使用 Livewire 的应用。然而,它缺少 Laravel Mix 支持的一些功能,例如将任意资源复制到构建中,而这些资源并未在你的 JavaScript 应用中直接引用。

迁移回 Mix

你是否已经使用我们的 Vite 脚手架启动了一个新的 Laravel 应用,但需要迁移回 Laravel Mix 和 webpack?没问题。请查阅我们的 从 Vite 迁移到 Mix 的官方指南

安装 & 设置

以下文档讨论了如何手动安装和配置 Laravel Vite 插件。然而,Laravel 的 入门套件 已经包含了所有这些脚手架,是开始使用 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-vue@vitejs/plugin-react

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 插件。当使用不受信任的证书时,你需要在浏览器中接受 Vite 开发服务器的证书警告,方法是运行 npm run dev 命令时点击控制台中的 "Local" 链接。

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

当在 Windows Subsystem for 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 客户端以启用热模块替换。在构建模式下,该指令将加载你编译和版本化的资源,包括任何导入的 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>

内联资源

有时可能需要包含资源的原始内容,而不是链接到资源的版本化 URL。例如,当将 HTML 内容传递给 PDF 生成器时,你可能需要直接将资源内容包含到你的页面中。你可以使用 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

别名

默认情况下,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 配置文件中。将 Vue 插件与 Laravel 一起使用时,你还需要一些额外的选项

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 的最快方式。

Inertia

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

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});

如果你正在将 Vite 的代码分割功能与 Inertia 一起使用,我们建议配置 资源预加载

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

URL 处理

当使用 Vite 并在你的应用的 HTML、CSS 或 JS 中引用资源时,有几个需要考虑的注意事项。首先,如果你使用绝对路径引用资源,Vite 将不会将该资源包含在构建中;因此,你应该确保该资源在你的 public 目录中可用。当使用专用 CSS 入口点时,你应该避免使用绝对路径,因为在开发期间,浏览器会尝试从 Vite 开发服务器(CSS 托管的位置)而不是从你的 public 目录加载这些路径。

当引用相对资源路径时,你应该记住路径是相对于引用它们的文件而言的。通过相对路径引用的任何资源都将由 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">

使用样式表

你可以在 Vite 文档 中了解更多关于 Vite 的 CSS 支持。如果你正在使用 PostCSS 插件(如 Tailwind),你可以在项目的根目录中创建一个 postcss.config.js 文件,Vite 将自动应用它

1export default {
2 plugins: {
3 tailwindcss: {},
4 autoprefixer: {},
5 },
6};

Laravel 的 入门套件 已经包含了正确的 Tailwind、PostCSS 和 Vite 配置。或者,如果你想在不使用我们的入门套件的情况下使用 Tailwind 和 Laravel,请查看 Tailwind 的 Laravel 安装指南

使用 Blade 和路由

使用 Vite 处理静态资源

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

但是,为了实现这一点,你需要通过将静态资源导入到应用的入口点来使 Vite 意识到你的资源。例如,如果你想处理和版本化存储在 resources/images 中的所有图像和存储在 resources/fonts 中的所有字体,你应该在应用的 resources/js/app.js 入口点中添加以下内容

1import.meta.glob([
2 '../images/**',
3 '../fonts/**',
4]);

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

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

保存时刷新

当你的应用使用传统的服务端渲染(使用 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});

别名

在 JavaScript 应用中,通常会创建别名以指向经常引用的目录。但是,你也可以通过在 Illuminate\Support\Facades\Vite 类上使用 macro 方法来创建在 Blade 中使用的别名。通常,“macros” 应该在 服务提供者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}

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

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

资源预加载

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

你可以指示 Laravel 通过在服务提供者boot 方法中调用 Vite::prefetch 方法来急切预加载你的资源

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>

自定义 Base URLs

如果你的 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);

Subresource Integrity (SRI)

如果你的 Vite manifest 包括你的资源的 integrity 哈希值,Laravel 将自动在其生成的任何脚本和样式标签上添加 integrity 属性,以便实施 Subresource Integrity。默认情况下,Vite 不会在其 manifest 中包含 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});

如果需要,你还可以自定义可以在其中找到 integrity 哈希值的 manifest 键

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 和整个 manifest

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});

更正开发服务器 URLs

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">

Laravel 是最有效率的方式来
构建、部署和监控软件。