资源打包
资源打包(Vite)
- 介绍
- 安装与设置
- 运行 Vite
- 使用 JavaScript
- 使用样式表
- 在 Blade 和路由中使用
- 资源预加载(Prefetching)
- 自定义基础 URL
- 环境变量
- 在测试中禁用 Vite
- 服务端渲染(SSR)
- 脚本和样式标签属性
- 高级自定义
介绍
Vite 是一个现代化的前端构建工具,它提供了极快的开发环境,并能将你的代码打包成生产环境可用的资源。
在使用 Laravel 构建应用时,通常会用 Vite 来打包应用的 CSS 和 JavaScript 文件,生成可用于生产的资源。
Laravel 与 Vite 无缝集成,提供了官方插件和 Blade 指令,用于在开发和生产环境中加载你的资源。
[!注意]
你还在使用 Laravel Mix 吗?在新的 Laravel 安装中,Vite 已经取代了 Laravel Mix。Mix 的文档请访问 Laravel Mix 官网。如果你想切换到 Vite,请查看我们的 迁移指南。
在 Vite 和 Laravel Mix 之间做选择
在过渡到 Vite 之前,新的 Laravel 应用在打包资源时使用的是 Mix,它由 webpack 驱动。Vite 专注于在构建复杂 JavaScript 应用时提供更快、更高效的体验。如果你正在开发一个单页应用(SPA),包括那些使用 Inertia 构建的应用,那么 Vite 将是完美的选择。
Vite 也非常适合带有 JavaScript “点缀”的传统服务端渲染应用,包括那些使用 Livewire 的应用。然而,它缺少一些 Laravel Mix 支持的功能,比如将任意资源复制到构建中(这些资源没有被直接引用在你的 JavaScript 应用里)。
迁移回 Mix
你是否已经使用我们的 Vite 脚手架开始了一个新的 Laravel 应用,但又需要回到 Laravel Mix 和 webpack?没问题。请参考我们的从 Vite 迁移到 Mix 的官方指南。
安装与设置
[!注意]
以下文档讨论如何手动安装和配置 Laravel Vite 插件。然而,Laravel 的 starter kits 已经包含了所有这些脚手架,它们是开始使用 Laravel 和 Vite 的最快方式。
安装 Node
你必须确保 Node.js(16+)和 NPM 已经安装好,才能运行 Vite 和 Laravel 插件:
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-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! 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 并且已经在应用上运行了 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', // [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 插件。
当使用不受信任的证书时,你需要在浏览器中接受 Vite 开发服务器的证书警告 —— 具体做法是,在运行 npm run dev
命令时,按照控制台中的 "Local" 链接进入并确认。
在 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 客户端,从而启用模块热替换(Hot Module Replacement,HMR)。在构建模式下,该指令会加载你已编译和带有版本号的资源,包括任何导入的 CSS。
如果需要,你在调用 @vite
指令时还可以指定已编译资源的构建路径:
<!doctype html>
<head>
{{-- 给定的构建路径是相对于 public 路径的 --}}
@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
命令,它会为应用的资源生成版本号并打包好,以便部署到生产环境:
# 运行 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 插件会在单文件组件(SFC)中重写资源 URL,
// 使它们指向 Laravel 的 Web 服务器。
// 将此设置为 `null`,则允许 Laravel 插件
// 把资源 URL 重写为指向 Vite 服务器。
base: null,
// Vue 插件会解析绝对 URL,并把它们当作磁盘上的绝对路径。
// 将此设置为 `false`,则保持绝对 URL 不变,
// 这样它们就能按预期引用 public 目录下的资源。
includeAbsolute: false,
},
},
}),
],
});
[!注意]
Laravel 的 starter kits 已经包含了适当的 Laravel、Vue 和 Vite 配置。
这些 starter kits 提供了开始使用 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
指令之前调用。
[!注意]
Laravel 的 starter kits 已经包含了适当的 Laravel、React 和 Vite 配置。
这些 starter kits 提供了开始使用 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 }) {
createApp({ render: () => h(App, props) })
.use(plugin)
.mount(el)
},
});
如果你在 Inertia 中使用 Vite 的代码分割功能,我们建议配置 资源预获取(asset prefetching)。
[!注意]
Laravel 的 starter kits 已经包含了适当的 Laravel、Inertia 和 Vite 配置。
这些 starter kits 提供了开始使用 Laravel、Inertia 和 Vite 的最快方式。
URL 处理
当你在应用的 HTML、CSS 或 JS 中使用 Vite 引用资源时,有一些注意事项。
首先,如果你用绝对路径引用资源,Vite 不会将该资源包含进构建;因此,你需要确保该资源存在于 public
目录中。
当你使用独立 CSS 入口文件时,应避免使用绝对路径。
因为在开发环境中,浏览器会尝试从 Vite 开发服务器(而不是 public
目录)加载这些路径下的 CSS。
当引用相对资源路径时,你需要记住这些路径是相对于引用它们的文件而言的。
任何通过相对路径引用的资源都会被 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">
使用样式表
[!注意]
Laravel 的 starter kits 已经包含了适当的 Tailwind 和 Vite 配置。
如果你想在不使用 starter kits 的情况下将 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 模板中引用的静态资源。
然而,为了实现这一点,你需要通过将静态资源导入到应用程序的入口点来让 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/**
监视 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 }
}],
}),
],
});
别名(Aliases)
在 JavaScript 应用程序中,创建别名 来引用经常使用的目录是很常见的。
但是,你也可以在 Blade 中使用 Illuminate\Support\Facades\Vite
类上的 macro
方法来创建别名。
通常情况下,“宏(macros)”应该在 服务提供者 的 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">
资源预加载(Asset Prefetching)
当使用 Vite 的代码分割功能构建单页应用(SPA)时,所需的资源会在每次页面导航时被获取。
这种行为可能导致 UI 渲染延迟。
如果这对你选择的前端框架来说是一个问题,Laravel 提供了一种方法,可以在初始页面加载时主动预取(prefetch)应用程序的 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();
}
默认情况下,预取会在 页面 load 事件 触发时开始。
如果你想自定义预取开始的时机,你可以指定一个 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(Custom Base URLs)
如果你的 Vite 编译资源部署在一个独立于应用的域名上(例如通过 CDN),你必须在应用的 .env
文件中指定 ASSET_URL
环境变量:
ASSET_URL=https://cdn.example.com
配置了资源 URL 之后,所有被重写过的资源 URL 都会自动加上你设置的前缀:
https://cdn.example.com/build/assets/app.9dce8d17.js
请记住,绝对 URL 不会被 Vite 重写,所以它们不会被加上前缀。
环境变量(Environment Variables)
你可以通过在应用的 .env
文件中为环境变量加上 VITE_
前缀,把它们注入到 JavaScript 里:
VITE_SENTRY_DSN_PUBLIC=http://example.com
你可以通过 import.meta.env
对象访问这些被注入的环境变量:
import.meta.env.VITE_SENTRY_DSN_PUBLIC
在测试中禁用 Vite(Disabling Vite in Tests)
Laravel 的 Vite 集成在运行测试时会尝试解析资源,这就要求你要么运行 Vite 开发服务器,要么先构建好资源。
如果你更希望在测试时模拟(mock)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, Server-Side Rendering)
Laravel 的 Vite 插件让你可以非常轻松地配置服务端渲染(SSR)。
首先,在 resources/js/ssr.js
里创建一个 SSR 入口文件,并在 Vite 配置里通过传递参数给 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,你可以改为使用 inertia:start-ssr
Artisan 命令来启动 SSR 服务器:
php artisan inertia:start-ssr
[!注意]
Laravel 的 starter kits 已经包含了正确的 Laravel、Inertia SSR 和 Vite 配置。这些 starter kits 提供了最快的方式来开始使用 Laravel、Inertia SSR 和 Vite。
脚本和样式标签属性
内容安全策略 (CSP) Nonce
如果你希望在脚本和样式标签上包含一个 nonce 属性,作为 内容安全策略 (CSP) 的一部分,你可以在自定义 中间件 中使用 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
{
/**
* 处理一个传入的请求。
*
* @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 starter kits 中附带的 Ziggy @route
指令,你可以使用 cspNonce
方法来获取它:
@routes(nonce: Vite::cspNonce())
如果你已经有一个想让 Laravel 使用的 nonce,你可以将该 nonce 传递给 useCspNonce
方法:
Vite::useCspNonce($nonce);
子资源完整性 (SRI)
如果你的 Vite manifest 包含了资源的 integrity
哈希,Laravel 会自动在其生成的任意脚本和样式标签上添加 integrity
属性,以强制启用 子资源完整性 (Subresource Integrity)。
默认情况下,Vite 不会在 manifest 中包含 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';// [tl! add]
export default defineConfig({
plugins: [
laravel({
// ...
}),
manifestSRI(),// [tl! add]
],
});
如果需要,你也可以自定义 manifest 中存放完整性哈希的键名:
use Illuminate\Support\Facades\Vite;
Vite::useIntegrityKey('custom-integrity-key');
如果你想完全禁用这个自动检测,你可以向 useIntegrityKey
方法传递 false
:
Vite::useIntegrityKey(false);
任意属性 (Arbitrary Attributes)
如果你需要在生成的脚本和样式标签上添加额外的属性,例如 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、manifest chunk 以及整个 manifest:
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,
]);
[!警告]
当 Vite 开发服务器运行时,$chunk
和$manifest
参数将为null
。
高级自定义 (Advanced Customization)
Laravel 的 Vite 插件开箱即用,使用了一些合理的默认约定,适用于大多数应用;但是,有时你可能需要自定义 Vite 的行为。为了启用额外的自定义选项,你可以使用以下方法和选项,而不是依赖 @vite
Blade 指令:
<!doctype html>
<head>
{{-- ... --}}
{{
Vite::useHotFile(storage_path('vite.hot')) // 自定义 "hot" 文件
->useBuildDirectory('bundle') // 自定义构建目录
->useManifestFilename('assets.json') // 自定义 manifest 文件名
->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', // 自定义 manifest 文件名
},
});
开发服务器的跨域资源共享 (Dev Server Cross-Origin Resource Sharing, CORS)
如果在浏览器中从 Vite 开发服务器获取资源时遇到跨域资源共享 (CORS) 问题,你可能需要为自定义来源授予访问权限。Vite 与 Laravel 插件组合后,默认允许以下来源,无需额外配置:
::1
127.0.0.1
localhost
*.test
*.localhost
APP_URL
in the project's.env
最简单的方法是确保你的应用程序 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: { // [tl! add]
cors: { // [tl! add]
origin: [ // [tl! add]
'https://backend.laravel', // [tl! add]
'http://admin.laravel:8566', // [tl! add]
], // [tl! add]
}, // [tl! add]
}, // [tl! add]
});
你也可以包含正则表达式模式,这在你希望允许某个顶级域名下的所有来源时非常有用,例如 *.laravel
:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: 'resources/js/app.js',
refresh: true,
}),
],
server: { // [tl! add]
cors: { // [tl! add]
origin: [ // [tl! add]
// Supports: SCHEME://DOMAIN.laravel[:PORT] [tl! add]
/^https?:\/\/.*\.laravel(:\d+)?$/, //[tl! add]
], // [tl! add]
}, // [tl! add]
}, // [tl! add]
});
修正开发服务器 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 提供资源时,输出的 URL 将指向 Vite 开发服务器:
- <img src="/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520"><!-- [tl! remove] -->
+ <img src="http://[::1]:5173/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520"><!-- [tl! add] -->
本译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。