资源打包 (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',
'resources/js/app.js',
]),
],
});相反,你应该通过 JavaScript 导入 CSS。通常,这会在应用程序的 resources/js/app.js 文件中完成:
import './bootstrap';
import '../css/app.css'; Laravel 插件还支持多个入口点和高级配置选项,例如 SSR 入口点。
使用安全的开发服务器
如果你的本地开发 Web 服务器通过 HTTPS 提供应用服务,则在连接到 Vite 开发服务器时可能会遇到问题。
如果你正在使用 Laravel Herd 并已保护站点安全,或者你正在使用 Laravel Valet 并已针对你的应用程序运行了 secure 命令,则 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',
}),
],
});当使用其他 Web 服务器时,你应该生成一个受信任的证书,并手动配置 Vite 使用生成的证书:
// ...
import fs from 'fs';
const host = 'my-app.test';
export default defineConfig({
// ...
server: {
host,
hmr: { host },
https: {
key: fs.readFileSync(`/path/to/${host}.key`),
cert: fs.readFileSync(`/path/to/${host}.crt`),
},
},
});如果你无法为系统生成受信任的证书,你可以安装并配置 @vitejs/plugin-basic-ssl 插件。当使用不受信任的证书时,你需要在运行 npm run dev 命令时,在浏览器中接受 Vite 开发服务器的证书警告(通过控制台中的“本地”链接)。
在 WSL2 上的 Sail 中运行开发服务器
当在 Windows Subsystem for Linux 2 (WSL2) 上的 Laravel Sail 中运行 Vite 开发服务器时,你应该在 vite.config.js 文件中添加以下配置,以确保浏览器能够与开发服务器通信:
// ...
export default defineConfig({
// ...
server: {
hmr: {
host: 'localhost',
},
},
});如果在开发服务器运行时文件更改没有反映在浏览器中,你可能还需要配置 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>
{{-- 给定的构建路径是相对于 public 路径的。 --}}
@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 中运行开发服务器,可能需要一些 额外的配置 选项。
使用 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: {
// Vue 插件会重写单文件组件中引用的资源 URL,
// 使其指向 Laravel Web 服务器。将此选项设置为 `null`
// 可让 Laravel 插件改为将资源 URL 重写为指向 Vite 服务器。
base: null,
// Vue 插件会解析绝对 URL,并将其视为磁盘上的绝对路径。
// 将此选项设置为 `false` 将保持绝对 URL 不变,使其可以按预期引用 public 目录中的资源。
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 处理
当使用 Vite 并在应用程序的 HTML、CSS 或 JS 中引用资源时,有几个注意事项需要考虑。首先,如果你使用绝对路径引用资源,Vite 不会将该资源包含在构建中;因此,你应该确保该资源在你的 public 目录中可用。当使用 专用的 CSS 入口点 时,你应该避免使用绝对路径,因为在开发期间,浏览器会尝试从托管 CSS 的 Vite 开发服务器加载这些路径,而不是从你的 public 目录。
当引用相对资源路径时,你应该记住这些路径是相对于引用它们的文件的。任何通过相对路径引用的资源都将被 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">使用样式表
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 文件中。
使用 Blade 和路由
使用 Vite 处理静态资源
当在 JavaScript 或 CSS 中引用资源时,Vite 会自动处理并为其添加版本号。此外,在构建基于 Blade 的应用时,Vite 也可以处理并为你仅在 Blade 模板中引用的静态资源添加版本号。
然而,为了实现这一点,您需要通过插件的 assets 选项指定您的资产,让 Vite 能够识别它们。例如,如果您想要处理并版本化存储在 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 类的测试:
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
{
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"
"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-ssrNOTE
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.
*
* @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 属性。
如果你需要在其他地方指定 nonce,包括 Laravel 的 入门套件 中包含的 Ziggy @route 指令,你可以使用 cspNonce 方法检索它:
@routes(nonce: Vite::cspNonce())如果你已经有一个 nonce,并且希望指示 Laravel 使用它,你可以将 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');如果你想完全禁用此自动检测,你可以向 useIntegrityKey 方法传递 false:
Vite::useIntegrityKey(false);任意属性
如果你需要在脚本和样式标签上包含其他属性,例如 data-turbo-track 属性,你可以通过 useScriptTagAttributes 和 useStyleTagAttributes 方法指定它们。通常,这些方法应该在 服务提供者 中调用:
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', // 自定义清单文件名...
},
});开发服务器跨域资源共享 (CORS)
如果你在从 Vite 开发服务器获取资源时在浏览器中遇到跨域资源共享 (CORS) 问题,你可能需要允许你的自定义源访问开发服务器。Vite 与 Laravel 插件结合允许以下源无需任何额外配置:
::1127.0.0.1localhost*.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: [
// 支持:SCHEME://DOMAIN.laravel[:PORT]
/^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="/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520">
<img src="http://[::1]:5173/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520">