资产捆绑(Vite)

Introduction

Vite 是一种现代前端构建工具,可提供极快的开发环境并捆绑您的生产代码。使用 Laravel 构建应用程序时,您通常会使用 Vite 将应用程序的 CSS 和 JavaScript 文件捆绑到生产就绪资产中。

Laravel 通过提供官方插件和 Blade 指令来与 Vite 无缝集成,以加载您的资产以进行开发和生产。

Note
你在运行 Laravel Mix 吗? Vite 在新的 Laravel 安装中取代了 Laravel Mix。有关 Mix 文档,请访问混合 网站。如果您想切换到 Vite,请查看我们的迁移指南.

在 Vite 和 Laravel Mix 之间做出选择

在过渡到 Vite 之前,新的 Laravel 应用程序使用了Mix, 由webpack,在捆绑资产时。 Vite 专注于在构建丰富的 JavaScript 应用程序时提供更快、更高效的体验。如果您正在开发单页应用程序 (SPA),包括使用以下工具开发的应用程序Inertia, Vite 将是完美的契合。

Vite 也可以很好地与传统的服务器端呈现的应用程序一起使用 JavaScript “sprinkles”,包括那些使用Livewire.但是,它缺少 Laravel Mix 支持的一些功能,例如将任意资产复制到未在 JavaScript 应用程序中直接引用的构建中的能力。

迁移回混合

您是否使用我们的 Vite 脚手架启动了一个新的 Laravel 应用程序,但需要返回到 Laravel Mix 和 webpack?没问题。请咨询我们的从 Vite 迁移到 Mix 的官方指南.

安装与设置

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

安装节点

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

node -v
npm -v

您可以使用简单的图形安装程序轻松安装最新版本的 Node 和 NPM节点官方网站.或者,如果您正在使用Laravel 风帆,您可以通过 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 代客 为当地的发展,并已运行安全命令 针对您的应用程序,您可以将 Vite 开发服务器配置为自动使用 Valet 生成的 TLS 证书:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            // ...
            valetTls: '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 命令。

加载脚本和样式

配置好你的 Vite 入口点后,你只需要在一个@vite() 您添加到的 Blade 指令<head> 您的应用程序的根模板:

<!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>
    {{-- Given build path is relative to public path. --}}

    @vite('resources/js/app.js', 'vendor/courier/build')
</head>

运行 Vite

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

或者,运行build 命令将对您的应用程序的资产进行版本控制和捆绑,并让它们为您部署到生产环境做好准备:

# Run the Vite development server...
npm run dev

# Build and version the assets for production...
npm run build

使用 JavaScript

Aliases

默认情况下,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: {
                    // The Vue plugin will re-write asset URLs, when referenced
                    // in Single File Components, to point to the Laravel web
                    // server. Setting this to `null` allows the Laravel plugin
                    // to instead re-write asset URLs to point to the Vite
                    // server instead.
                    base: null,

                    // The Vue plugin will parse absolute URLs and treat them
                    // as absolute paths to files on disk. Setting this to
                    // `false` will leave absolute URLs un-touched so they can
                    // reference assets in the public directory as expected.
                    includeAbsolute: false,
                },
            },
        }),
    ],
});

Note
Laravel 的入门套件 已经包含适当的 Laravel、Vue 和 Vite 配置。查看Laravel 微风 以最快的方式开始使用 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 扩展,记得更新你的入口点,如果需要的话,作为如上所示.

您还需要包括额外的@viteReactRefresh Blade 指令与现有的@vite 指示。

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

@viteReactRefresh 指令必须在@vite 指示。

Note
Laravel 的入门套件 已经包含适当的 Laravel、React 和 Vite 配置。查看Laravel 微风 以最快的方式开始使用 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)
  },
});

Note
Laravel 的入门套件 已经包含适当的 Laravel、Inertia 和 Vite 配置。查看Laravel 微风 以最快的方式开始使用 Laravel、Inertia 和 Vite。

网址处理

在应用程序的 HTML、CSS 或 JS 中使用 Vite 和引用资产时,需要考虑一些注意事项。首先,如果您使用绝对路径引用资产,Vite 将不会在构建中包含该资产;因此,您应该确保资产在您的公共目录中可用。

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

考虑以下项目结构:

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

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

<!-- This asset is not handled by Vite and will not be included in the build -->
<img src="/taylor.png">

<!-- This asset will be re-written, versioned, and bundled by Vite -->
<img src="../../images/abigail.png">

使用样式表

你可以在访问文档.如果您使用的是 PostCSS 插件,例如Tailwind, 你可以创建一个postcss.config.js 文件放在项目的根目录下,Vite 会自动应用它:

module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    },
};

Note Laravel 的入门套件 已经包括适当的 Tailwind、PostCSS 和 Vite 配置。或者,如果您想在不使用我们的入门套件之一的情况下使用 Tailwind 和 Laravel,请查看Tailwind 的 Laravel 安装指南.

使用刀片和路由

使用 Vite 处理静态资源

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

然而,为了实现这一点,您需要通过将静态资产导入应用程序的入口点,让 Vite 了解您的资产。例如,如果你想处理和版本存储在resources/images 以及存储在resources/fonts, 你应该在你的应用程序中添加以下内容resources/js/app.js 入口点:

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

这些资产现在将在运行时由 Vite 处理npm run build.然后你可以在 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:

看着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 中使用,方法是使用macro 上的方法Illuminate\Support\Facades\Vite 班级。通常,“宏”应该在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">

自定义基本 URL

如果您的 Vite 编译资产被部署到与您的应用程序分开的域,例如通过 CDN,您必须指定ASSET_URL 应用程序中的环境变量.env 文件:

ASSET_URL=https://cdn.example.com

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

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

请记住绝对 URL 不会被 Vite 重写, 所以他们不会有前缀。

环境变量

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

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 班级:

use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function test_without_vite_example(): void
    {
        $this->withoutVite();

        // ...
    }
}

如果你想为所有测试禁用 Vite,你可以调用withoutVite 方法来自setUp 在你的基础上的方法TestCase 班级:

<?php

namespace Tests;

use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;

    protected function setUp(): void// [tl! add:start]
    {
        parent::setUp();

        $this->withoutVite();
    }// [tl! add:end]
}

服务器端渲染 (SSR)

Laravel Vite 插件可以轻松地使用 Vite 设置服务器端渲染。首先,在以下位置创建一个 SSR 入口点resources/js/ssr.js 并通过将配置选项传递给 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 创建您的 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.mjs

Note
Laravel 的入门套件 已经包含适当的 Laravel、Inertia SSR 和 Vite 配置。查看Laravel 微风 以最快的方式开始使用 Laravel、Inertia SSR 和 Vite。

脚本和样式标记属性

内容安全策略 (CSP) Nonce

如果你想包括一个nonce 属性 在您的脚本和样式标签上作为您的一部分内容安全政策,您可以使用useCspNonce 自定义方法middleware:

<?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, string $role): Response
    {
        Vite::useCspNonce();

        return $next($request)->withHeaders([
            'Content-Security-Policy' => "script-src 'nonce-".Vite::cspNonce()."'",
        ]);
    }
}

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

如果您需要在其他地方指定随机数,包括齐吉@route 指示 包含在 Laravel 中入门套件,您可以使用cspNonce 方法:

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

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

Vite::useCspNonce($nonce);

子资源完整性 (SRI)

如果你的 Vite manifest 包含integrity 为你的资产哈希,Laravel 会自动添加integrity 它生成的任何脚本和样式标签的属性,以强制执行子资源完整性.默认情况下,Vite 不包含integrity hash 在其清单中,但您可以通过安装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]
    ],
});

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

use Illuminate\Support\Facades\Vite;

Vite::useIntegrityKey('custom-integrity-key');

如果您想完全禁用此自动检测,您可以通过falseuseIntegrityKey 方法:

Vite::useIntegrityKey(false);

任意属性

如果您需要在脚本和样式标签中包含其他属性,例如data-turbo-track 属性,您可以通过useScriptTagAttributesuseStyleTagAttributes 方法。通常,应该从一个服务提供者:

use Illuminate\Support\Facades\Vite;

Vite::useScriptTagAttributes([
    'data-turbo-track' => 'reload', // Specify a value for the attribute...
    'async' => true, // Specify an attribute without a value...
    'integrity' => false, // Exclude an attribute that would otherwise be included...
]);

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
$chunk$manifest 争论将是null 当 Vite 开发服务器运行时。

高级定制

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

<!doctype html>
<head>
    {{-- ... --}}

    {{
        Vite::useHotFile(storage_path('vite.hot')) // Customize the "hot" file...
            ->useBuildDirectory('bundle') // Customize the build directory...
            ->useManifestFilename('assets.json') // Customize the manifest filename...
            ->withEntryPoints(['resources/js/app.js']) // Specify the entry points...
    }}
</head>

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

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';

export default defineConfig({
    plugins: [
        laravel({
            hotFile: 'storage/vite.hot', // Customize the "hot" file...
            buildDirectory: 'bundle', // Customize the build directory...
            input: ['resources/js/app.js'], // Specify the entry points...
        }),
    ],
    build: {
      manifest: 'assets.json', // Customize the manifest filename...
    },
});

更正开发服务器 URL

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

例如,vite-imagetools 当 Vite 为您的资产提供服务时,插件会输出如下 URL:

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

vite-imagetools 插件期望输出 URL 将被 Vite 拦截,然后插件可以处理所有以开头的 URL/@imagetools.如果您使用的插件期望出现这种行为,则需要手动更正 URL。你可以在你的vite.config.js 通过使用文件transformOnServe 选项。

在此特定示例中,我们会将开发服务器 URL 附加到所有出现的/@imagetools 在生成的代码中:

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 为 Assets 提供服务时,它会输出指向 Vite 开发服务器的 URL:

- <img src="/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520"><!-- [tl! remove] -->
+ <img src="http://[::1]:5173/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520"><!-- [tl! add] -->
豫ICP备18041297号-2