fabricity/vite-bundle

A lightweight Symfony bundle that provides seamless Vite integration with automatic dev-server detection, manifest handling, and simple Twig helpers for loading compiled assets.

Maintainers

Package info

github.com/fabricity/vite-bundle

Type:symfony-bundle

pkg:composer/fabricity/vite-bundle

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-05-09 10:04 UTC

This package is auto-updated.

Last update: 2026-05-09 10:04:54 UTC


README

Code Quality PHPUnit PHPStan

A lightweight Symfony bundle that integrates Vite into your Symfony application. It automatically detects the Vite dev server, reads the production manifest, and exposes simple Twig globals for loading compiled assets.

Features

  • Automatic Vite dev server detection
  • Production manifest (manifest.json) parsing
  • Multiple independent build support (e.g. frontend / backend)
  • Symfony Asset VersionStrategyInterface integration
  • Twig globals (vite.dev, vite.devClient) for conditional script loading

Philosophy

This bundle resolves asset URLs through the Vite manifest and the Symfony Asset component — nothing more. It does not auto-generate <script>, <link>, or <link rel="modulepreload"> tags for you.

This is intentional. You stay in full control of your HTML: which assets to preload, where to place scripts, whether to add async, defer, crossorigin, or integrity attributes. The bundle gives you the correct URLs; you decide how to load them.

Requirements

  • PHP 8.4+
  • Symfony 6.4, 7.4, or 8.0

Installation

composer require fabricity/vite-bundle

Register the bundle in config/bundles.php:

return [
    // ...
    Fabricity\Bundle\ViteBundle\FabricityViteBundle::class => ['all' => true],
];

Vite Setup

Install Vite in your project:

npm install --save-dev vite

Create a vite.config.js at the root of your project:

import {defineConfig} from 'vite'

export default defineConfig({
    build: {
        manifest: true,
        outDir: 'public/build/frontend',
        rollupOptions: {
            input: 'assets/main.js',
        },
    },
    server: {
        origin: 'http://localhost:5173',
    },
})

Add the following scripts to your package.json:

{
    "scripts": {
        "dev": "vite",
        "build": "vite build"
    }
}

Run npm run dev during development and npm run build for production.

Configuration

Create config/packages/fabricity_vite.yaml:

fabricity_vite:
    # Path to your public directory (default: %kernel.project_dir%/public)
    public_dir: '%kernel.project_dir%/public'

    # Vite dev server URL (omit in production)
    server: 'http://localhost:5173'

    # One entry per Vite build output
    builds:
        frontend:
            build_dir: build/frontend
            # manifest_path defaults to .vite/manifest.json
        backend:
            build_dir: build/backend

Each entry under builds registers a Symfony Asset version strategy service named fabricity_vite.version_strategy.<name>.

Multiple builds

You can define as many builds as you need. This is useful when you have separate Vite configs for different parts of your application.

Twig integration

The bundle registers a Twig extension that exposes a global vite variable:

Variable Type Description
vite.dev bool true when the Vite dev server is reachable
vite.devClient string|null URL to the Vite HMR client (/@vite/client)

Use it in your base template to conditionally load the dev client:

{% if vite.dev %}
    <script type="module" src="{{ vite.devClient }}"></script>
{% endif %}

Asset version strategy

Register the bundle's version strategy on a Symfony Asset package in config/packages/assets.yaml:

framework:
    assets:
        packages:
            frontend:
                version_strategy: 'fabricity_vite.version_strategy.frontend'
            backend:
                version_strategy: 'fabricity_vite.version_strategy.backend'

Then use the standard Symfony asset() helper in Twig:

{# In dev mode: points to http://localhost:5173/src/main.js #}
{# In prod mode: resolves via manifest to /build/frontend/assets/main-abc123.js #}
<script type="module" src="{{ asset('src/main.js', 'frontend') }}"></script>
<link rel="stylesheet" href="{{ asset('src/main.css', 'frontend') }}">

CSS co-located with JS

When Vite bundles CSS alongside a JS entry point, you can reference the CSS file using its .css extension even though it is listed under a .js key in the manifest:

<link rel="stylesheet" href="{{ asset('src/app.css', 'frontend') }}">

The bundle automatically resolves src/app.csssrc/app.jscss[0] from the manifest.

Full example

{# templates/base.html.twig #}
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="{{ asset('src/main.css', 'frontend') }}">
</head>
<body>
    {% block body %}{% endblock %}

    {% if vite.dev %}
        <script type="module" src="{{ vite.devClient }}"></script>
    {% endif %}
    <script type="module" src="{{ asset('src/main.js', 'frontend') }}"></script>
</body>
</html>

License

MIT — see LICENSE.