- Введение
- Установка и настройка
- Запуск Vite
- Работа с JavaScript
- Работа со стилями
- Работа с Blade и маршрутами
- Пользовательские базовые URL
- Переменные окружения
- Отключение Vite в тестах
- Серверный рендеринг (SSR)
- Атрибуты тегов script и style
- Продвинутая настройка
#Введение
Vite — современный инструмент сборки фронтенда, обеспечивающий очень быструю среду разработки и упаковку кода для продакшена. При создании приложений на Laravel обычно используют Vite для сборки CSS и JavaScript файлов приложения в готовые к продакшену ассеты.
Laravel интегрируется с Vite через официальный плагин и Blade-директиву для загрузки ассетов как в режиме разработки, так и в продакшене.
Вы используете Laravel Mix? Vite заменил Laravel Mix в новых установках Laravel. Документацию по Mix смотрите на сайте Laravel Mix. Если хотите перейти на Vite, ознакомьтесь с нашим гайдом по миграции.
#Выбор между Vite и Laravel Mix
Ранее новые приложения Laravel использовали Mix, основанный на webpack, для сборки ассетов. Vite ориентирован на более быструю и продуктивную разработку сложных JavaScript-приложений. Если вы создаёте SPA, включая приложения на базе Inertia, Vite будет идеальным выбором.
Vite также хорошо работает с традиционными серверно-рендеренными приложениями с небольшими JavaScript-вставками, включая проекты с Livewire. Однако ему не хватает некоторых возможностей Laravel Mix, например, копирования произвольных ассетов, не подключённых напрямую в JavaScript.
#Возврат к Mix
Если вы начали новый проект Laravel с использованием Vite, но хотите вернуться к Laravel Mix и webpack, это не проблема. Ознакомьтесь с нашим официальным руководством по миграции с Vite на Mix.
#Установка и настройка
В этом разделе описывается ручная установка и настройка плагина Laravel Vite. Однако стартовые наборы Laravel (starter kits) уже включают всю необходимую структуру и являются самым быстрым способом начать работу с Laravel и Vite.
#Установка Node
Перед запуском Vite и плагина Laravel убедитесь, что установлены Node.js (версия 16 и выше) и NPM:
node -v
npm -v
Вы можете легко установить последнюю версию Node и NPM с помощью графических установщиков с официального сайта Node. Или, если вы используете Laravel Sail, можно запускать Node и NPM через Sail:
./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, лучше не указывать CSS точки входа:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel([
'resources/css/app.css',
'resources/js/app.js',
]),
],
});
Вместо этого импортируйте CSS через JavaScript. Обычно это делается в файле resources/js/app.js вашего приложения:
import './bootstrap';
import '../css/app.css';
Плагин Laravel также поддерживает несколько точек входа и расширенные опции конфигурации, такие как SSR точки входа.
#Работа с защищённым сервером разработки
Если ваш локальный сервер разработки обслуживает приложение по 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',
}),
],
});
При использовании другого веб-сервера следует сгенерировать доверенный сертификат и вручную настроить 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. При использовании недоверенных сертификатов в браузере придётся принять предупреждение о сертификате для сервера разработки Vite, перейдя по ссылке "Local" в консоли при запуске команды npm run dev.
#Запуск сервера разработки в Sail на WSL2
При запуске сервера разработки Vite в Laravel Sail на Windows Subsystem for Linux 2 (WSL2) добавьте следующую конфигурацию в vite.config.js, чтобы браузер мог корректно общаться с сервером разработки:
// ...
export default defineConfig({
// ...
server: {
hmr: {
host: 'localhost',
},
},
});
Если изменения файлов не отображаются в браузере при запущенном сервере разработки, возможно, потребуется настроить опцию Vite server.watch.usePolling.
#Подключение скриптов и стилей
После настройки точек входа Vite вы можете подключить их с помощью Blade-директивы @vite(), добавленной в <head> корневого шаблона вашего приложения:
<!doctype html>
<head>
{{-- ... --}}
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
Если вы импортируете CSS через JavaScript, достаточно указать только точку входа JavaScript:
<!doctype html>
<head>
{{-- ... --}}
@vite('resources/js/app.js')
</head>
Директива @vite автоматически обнаружит сервер разработки Vite и подключит клиент для поддержки горячей замены модулей (HMR). В режиме сборки директива загрузит скомпилированные и версионированные ассеты, включая импортированные CSS.
При необходимости вы можете указать путь к сборке скомпилированных ассетов при вызове директивы @vite:
<!doctype html>
<head>
{{-- Given build path is relative to public path. --}}
@vite('resources/js/app.js', 'vendor/courier/build')
</head>
#Встраиваемые ассеты
Иногда нужно включить содержимое ассетов напрямую, а не ссылаться на версионированный URL. Например, при передаче HTML в генератор PDF. Вы можете вывести содержимое ассетов Vite с помощью метода content фасада Vite:
@php
use Illuminate\Support\Facades\Vite;
@endphp
<!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
Если вы запускаете сервер разработки в Sail на WSL2, возможно, потребуется дополнительная конфигурация.
#Работа с 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. При использовании Vue с Laravel потребуются дополнительные опции:
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 ассетов, когда они
// используются в Single File Components, чтобы
// указывать на веб-сервер Laravel.
// Установка в `null` позволяет плагину Laravel
// переписать URL ассетов так, чтобы они указывали
// на сервер Vite.
base: null,
// Плагин Vue будет обрабатывать абсолютные URL как
// абсолютные пути к файлам на диске.
// Установка в `false` оставит абсолютные URL без изменений,
// чтобы они ссылались на ассеты в публичной директории.
includeAbsolute: false,
},
},
}),
],
});
Стартовые наборы Laravel (starter kits) уже включают правильную конфигурацию Laravel, Vue и Vite. Ознакомьтесь с Laravel Breeze — самый быстрый способ начать работу с 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, и при необходимости обновите точку входа, как показано выше.
Также нужно добавить дополнительную Blade-директиву @viteReactRefresh рядом с существующей @vite.
@viteReactRefresh
@vite('resources/js/app.jsx')
Директива @viteReactRefresh должна вызываться перед директивой @vite.
Стартовые наборы Laravel (starter kits) уже включают правильную конфигурацию Laravel, React и Vite. Ознакомьтесь с Laravel Breeze — самый быстрый способ начать работу с 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)
},
});
Стартовые наборы Laravel (starter kits) уже включают правильную конфигурацию Laravel, Inertia и Vite. Ознакомьтесь с Laravel Breeze — самый быстрый способ начать работу с Laravel, Inertia и Vite.
#Обработка URL
При использовании Vite и ссылках на ассеты в HTML, CSS или JS вашего приложения есть несколько особенностей. Во-первых, если вы используете абсолютный путь к ассету, Vite не включит его в сборку; убедитесь, что такой ассет доступен в публичной директории.
При использовании относительных путей помните, что они считаются относительно файла, в котором используются. Все ассеты с относительными путями будут переписаны, версионированы и упакованы 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">
#Работа со стилями
Подробнее о поддержке CSS в Vite можно узнать в документации Vite. Если вы используете PostCSS-плагины, например Tailwind, создайте файл postcss.config.js в корне проекта — Vite применит его автоматически:
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};
Стартовые наборы Laravel (starter kits) уже включают правильную конфигурацию Tailwind, PostCSS и Vite. Если хотите использовать Tailwind и Laravel без стартовых наборов, смотрите гайд по установке Tailwind для Laravel.
#Работа с Blade и маршрутами
#Обработка статических ассетов с помощью Vite
При ссылках на ассеты в JavaScript или CSS Vite автоматически обрабатывает и версионирует их. Кроме того, при создании приложений на Blade Vite может обрабатывать и версионировать статические ассеты, используемые только в шаблонах Blade.
Для этого нужно импортировать статические ассеты в точку входа приложения. Например, чтобы обработать и версионировать все изображения из 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:
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-приложениях часто создают алиасы для часто используемых директорий. Вы также можете создавать алиасы для использования в Blade, используя метод macro класса Illuminate\Support\Facades\Vite. Обычно "макросы" определяют в методе 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">
#Пользовательские базовые URL
Если скомпилированные ассеты Vite размещены на отдельном домене, например через CDN, необходимо указать переменную окружения ASSET_URL в файле .env вашего приложения:
ASSET_URL=https://cdn.example.com
После настройки 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 в тестах
Интеграция Vite в Laravel пытается разрешить ваши ассеты во время тестов, что требует запущенного сервера разработки Vite или сборки ассетов.
Если хотите подменить Vite в тестах, вызовите метод withoutVite, доступный в тестах, расширяющих класс TestCase Laravel:
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
{
parent::setUp();
$this->withoutVite();
}
}
#Серверный рендеринг (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-точку входа, рекомендуем дополнить скрипт "build" в package.json вашего приложения для создания SSR-сборки:
"scripts": {
"dev": "vite",
"build": "vite build"
"build": "vite build && vite build --ssr"
}
Затем для сборки и запуска SSR-сервера выполните следующие команды:
npm run build
node bootstrap/ssr/ssr.js
Если вы используете SSR с Inertia, можно запустить SSR-сервер командой Artisan inertia:start-ssr:
php artisan inertia:start-ssr
Стартовые наборы Laravel (starter kits) уже включают правильную конфигурацию Laravel, Inertia SSR и Vite. Ознакомьтесь с Laravel Breeze — самый быстрый способ начать работу с Laravel, Inertia SSR и Vite.
#Атрибуты тегов script и style
#Nonce для Content Security Policy (CSP)
Если хотите добавить атрибут nonce к тегам script и style в рамках вашей Content Security Policy, можно сгенерировать или указать 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
{
/**
* Обработка входящего запроса.
*
* @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 ко всем сгенерированным тегам script и style.
Если нужно указать nonce в другом месте, включая Ziggy @route директиву, которая входит в состав стартовых наборов Laravel, его можно получить с помощью метода cspNonce:
@routes(nonce: Vite::cspNonce())
Если у вас уже есть nonce, который вы хотите использовать, передайте его в метод useCspNonce:
Vite::useCspNonce($nonce);
#Проверка целостности субресурсов (SRI)
Если манифест Vite содержит хэши integrity для ассетов, Laravel автоматически добавит атрибут integrity к тегам script и style для обеспечения Subresource Integrity. По умолчанию Vite не включает integrity в манифест, но вы можете включить это, установив NPM-плагин vite-plugin-manifest-sri:
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');
Если хотите полностью отключить автодетекцию, передайте false в метод useIntegrityKey:
Vite::useIntegrityKey(false);
#Произвольные атрибуты
Если нужно добавить дополнительные атрибуты к тегам script и style, например 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',
]);
Если нужно условно добавлять атрибуты, можно передать callback, который получит путь к исходному ассету, его 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,
]);
Аргументы $chunk и $manifest будут равны null, пока запущен сервер разработки Vite.
#Продвинутая настройка
Из коробки плагин Laravel Vite использует разумные настройки, подходящие большинству приложений. Однако иногда требуется изменить поведение Vite. Для расширенной настройки доступны методы и опции, которые можно использовать вместо Blade-директивы @vite:
<!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', // Настроить имя файла манифеста...
},
});
#Коррекция URL дев-сервера
Некоторые плагины Vite предполагают, что URL, начинающиеся с косой черты, всегда указывают на сервер разработки Vite. Однако из-за особенностей интеграции с Laravel это не так.
Например, плагин vite-imagetools генерирует 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 обслуживает ассеты, он будет выводить URL, указывающие на сервер разработки Vite:
- <img src="/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520">
+ <img src="http://[::1]:5173/@imagetools/f0b2f404b13f052c604e632f2fb60381bf61a520">