Content Index
- How @vite() works in Laravel
- What is meant by “@vite custom attributes”
- ❌ What does NOT work (and often causes confusion)
- ❌ vite.config.js does not control HTML attributes
- ❌ @vite([...], ['async']) does not exist in Laravel
- ✅ The correct way: custom attributes with Vite in Laravel
- Comparison with other approaches (Symfony and pure Vite)
- Vite Plugins (Hackernoon)
- Can conditional attributes be used per environment?
- Can attributes be defined per file?
- Conclusion
When working with Laravel and Vite, it is common to use the @vite() directive to load our CSS and JavaScript files. However, a very common question is how to customize the HTML attributes that are automatically generated in the <script> and <link> tags.
In this article, I explain how custom attributes really work in @vite, what can and cannot be done, and what the correct approach is according to the Laravel + Vite stack, avoiding incorrect or confusing configurations.
How @vite() works in Laravel
To load our CSS and JS files in Laravel with Vite using:
@vite(['resources/css/blog.css'])
@vite(['resources/js/blog.js'])In our blade files; at the time of rendering, we obtain HTML tags such as:
<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>Key point:
- Vite does not render these tags.
Laravel is the one that generates the final HTML, using the information produced by Vite.
Therefore, any customization of HTML attributes is not done in vite.config.js, but from Laravel.
What is meant by “@vite custom attributes”
When we talk about custom attributes, we refer to:
- async
- defer
- data-*
- integrity
- crossorigin
- attributes for Turbo, SEO, or tracking
Example:
<script async data-turbo-track="reload"></script>
<link data-custom="value">❌ What does NOT work (and often causes confusion)
Before diving into the correct solution, it is important to clarify several common mistakes that even appear in technical articles.
❌ vite.config.js does not control HTML attributes
Options such as:
- build.rollupOptions.output.assetFileNames
- Vite plugins
- conditional config (defineConfig)
CANNOT add or modify <script> or <link> attributes.
These options only affect:
- file names
- bundling
- plugins
- proxy
- build optimization
❌ @vite([...], ['async']) does not exist in Laravel
Laravel does not allow passing HTML attributes as a second parameter to @vite().
Any example of this type is incorrect:
@vite(['resources/js/app.js'], ['async']) ❌✅ The correct way: custom attributes with Vite in Laravel
Laravel exposes an official API to modify the attributes of the tags generated by @vite.
This is done from a Service Provider. Which brings us to the following question:
What if you want to customize at the attribute level, for example, the async for JavaScript?
To do this, we can add the modifications to our 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,
]);
}
}Customize global <link> attributes:
Vite::useStyleTagAttributes([
'data-turbo-track' => 'reload',
]);Resulting HTML:
<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>- ✔️ No hacks
- ✔️ No unnecessary plugins
- ✔️ Fully supported by Laravel
Therefore, this is the way we should follow to customize the attributes of the script and link tags with Vite and Laravel.
Comparison with other approaches (Symfony and pure Vite)
- Symfony + Vite (Pentatrion)
- Symfony allows:
- Global attributes
- Local attributes
- Events (RenderAssetTagEvent)
- Symfony allows:
- Laravel does not have equivalent events, so:
- Control is global
- Not per individual asset
This explains why some Symfony guides do not apply directly to Laravel.
Vite Plugins (Hackernoon)
Vite plugins are used to:
- Modify the build
- Intercept requests
- Generate files
- Middleware in dev server
They do not affect the HTML generated by Laravel.
They are useful only if you need build logic, not HTML attributes.
Can conditional attributes be used per environment?
Yes, but from Laravel, not from Vite.
Example:
Vite::useScriptTagAttributes(
app()->isProduction()
? ['defer' => true]
: ['async' => true]
);Can attributes be defined per file?
❌ Not natively.
Alternatives:
- render scripts manually
- create custom helpers
- use @env in Blade
- separate Vite entries
Conclusion
If you are using Laravel with Vite and need custom attributes in @vite, the only correct way is to do it from the Vite facade in Laravel.
- ❌ Not from vite.config.js
- ❌ Not with plugins
- ❌ Not by passing attributes to @vite()
✔️ Use Vite::useScriptTagAttributes()
✔️ Use Vite::useStyleTagAttributes()
This approach is clean, maintainable, and compatible with future versions.