Atributos personalizados en @vite en Laravel

Video thumbnail

Cuando trabajamos con Laravel y Vite, es habitual usar la directiva @vite() para cargar nuestros archivos CSS y JavaScript. Sin embargo, una duda muy común es cómo personalizar los atributos HTML que se generan automáticamente en las etiquetas <script> y <link>.

En este artículo explico cómo funcionan realmente los atributos personalizados en @vite, qué se puede y qué no se puede hacer, y cuál es el enfoque correcto según el stack Laravel + Vite, evitando configuraciones incorrectas o confusas.

Cómo funciona @vite() en Laravel

Para cargar nuestros archivos CSS y JS en Laravel con vite mediante:

@vite(['resources/css/blog.css'])
@vite(['resources/js/blog.js'])

En nuestros archivos blade; al momento del renderizado, obtenemos las etiquetas de HTML como:

<link rel="preload" as="style" href="https://www.desarrollolibre.net/build/assets/blog-6Y1hNTHC.css" />
<script type="module" src="https://www.desarrollolibre.net/build/assets/blog-Bdalpt8p.js"></script>

Punto clave:

  • Vite no renderiza estas etiquetas.

Laravel es quien genera el HTML final, usando la información producida por Vite.

Por eso, cualquier personalización de atributos HTML no se hace en vite.config.js, sino desde Laravel.

Qué se entiende por “atributos personalizados @vite”

Cuando hablamos de atributos personalizados, nos referimos a:

  • async
  • defer
  • data-*
  • integrity
  • crossorigin
  • atributos para Turbo, SEO o tracking

Ejemplo:

<script async data-turbo-track="reload"></script>
<link data-custom="value">

❌ Lo que NO funciona (y suele causar confusión)

Antes de entrar en la solución correcta, es importante aclarar varios errores comunes que aparecen incluso en artículos técnicos.

❌ vite.config.js no controla atributos HTML

Opciones como:

  • build.rollupOptions.output.assetFileNames
  • plugins de Vite
  • config condicional (defineConfig)

NO pueden añadir ni modificar atributos <script> o <link>.

Estas opciones solo afectan:

  • nombres de archivos
  • bundling
  • plugins
  • proxy
  • optimización de build

❌ @vite([...], ['async']) no existe en Laravel

Laravel no permite pasar atributos HTML como segundo parámetro a @vite().

Cualquier ejemplo de este tipo es incorrecto:

@vite(['resources/js/app.js'], ['async']) ❌

✅ Forma correcta: atributos personalizados con Vite en Laravel

Laravel expone una API oficial para modificar los atributos de las etiquetas generadas por @vite.

Esto se hace desde un Service Provider. Lo cual nos trae a la siguiente pregunta:

¿Qué pasa si quieres personalizar a nivel de atributos, por ejemplo, el async para los JavaScript?

Para ello, podemos agregar las modificaciones a nuestro provider:

app/Providers/AppServiceProvider.php

use Illuminate\Support\Facades\Vite;
***
class AppServiceProvider extends ServiceProvider
{
    ***
    public function boot(): void
    {
        Vite::useScriptTagAttributes([
         'data-turbo-track' => 'reload', 
         'async' => true, 
         'integrity' => false, 
       ]);
 

    }
}

Personalizar atributos globales de <link>:

Vite::useStyleTagAttributes([
    'data-turbo-track' => 'reload', 
]);

HTML resultante:

<link rel="preload"
     as="style"
     href="/build/assets/blog.css"
     data-turbo-track="reload">
<script type="module"
       src="/build/assets/blog.js"
       async
       data-turbo-track="reload">
</script>
  • ✔️ Sin hacks
  • ✔️ Sin plugins innecesarios
  • ✔️ Totalmente soportado por Laravel

Por lo tanto, de esta forma es la que debemos de seguir para poder personalizar los atributos de las etiquetas de script y link con vite y Laravel.

Comparación con otros enfoques (Symfony y Vite puro)

  • Symfony + Vite (Pentatrion)
    • Symfony permite:
      • Atributos globales
      • Atributos locales
      • Eventos (RenderAssetTagEvent)
  • Laravel no tiene eventos equivalentes, por lo que:
    • El control es global
    • No por asset individual

Esto explica por qué algunas guías de Symfony no aplican directamente a Laravel.

Plugins de Vite (Hackernoon)

Los plugins de Vite sirven para:

  • Modificar el build
  • Interceptar requests
  • Generar archivos
  • Middleware en dev server

No afectan al HTML generado por Laravel.

Son útiles solo si necesitas lógica de build, no atributos HTML.

¿Se pueden usar atributos condicionales por entorno?

Sí, pero desde Laravel, no desde Vite.

Ejemplo:

Vite::useScriptTagAttributes(
   app()->isProduction()
       ? ['defer' => true]
       : ['async' => true]
);

¿Se pueden definir atributos por archivo?

❌ No de forma nativa.

Alternativas:

  • renderizar scripts manualmente
  • crear helpers personalizados
  • usar @env en Blade
  • separar entradas Vite

Conclusión

Si estás usando Laravel con Vite y necesitas atributos personalizados en @vite, la única forma correcta es hacerlo desde el facade Vite en Laravel.

  • ❌ No desde vite.config.js
  • ❌ No con plugins
  • ❌ No pasando atributos a @vite()

✔️ Usa Vite::useScriptTagAttributes()

✔️ Usa Vite::useStyleTagAttributes()

Este enfoque es limpio, mantenible y compatible con futuras versiones.

Aprende cómo usar atributos personalizados en @vite con Laravel. Añade async, data-* y otros atributos a scripts y estilos de forma correcta y soportada.

Acepto recibir anuncios de interes sobre este Blog.

Andrés Cruz

EN In english