Using Assets in Templates
Work in progress
This page is a work in progress. Help complete it by contributing on GitHub!
- Twig Helper Functions
- Typical Template Usage
- Loading Multiple Entry Points
- Static Assets
- Troubleshooting
- Next Steps
Now that Vite is compiling your assets, let's learn how to actually use them in your templates! UserFrosting provides simple Twig functions that handle all the complexity behind the scenes. You'll be amazed at how easy this is.
Twig Helper Functions
UserFrosting includes three main Twig functions for loading Vite assets:
vite_js()
Loads a JavaScript entry point and includes the proper <script> tag.
{{ vite_js('main.ts') }}
Output in development mode:
<script type="module" src="http://localhost:5173/@vite/client"></script>
<script type="module" src="http://localhost:5173/main.ts"></script>
Output in production mode:
<script type="module" crossorigin src="/assets/main-a1b2c3d4.js"></script>
vite_css()
Loads CSS associated with an entry point. In development, Vite injects CSS automatically via JavaScript, so this may not output anything. In production, it outputs a <link> tag.
{{ vite_css('main.ts') }}
Output in production mode:
<link rel="stylesheet" href="/assets/main-a1b2c3d4.css">
Note
In development mode with HMR, CSS is injected dynamically by Vite's JavaScript. The vite_css() function typically doesn't output anything in dev mode, as the styles are loaded by the Vite dev server.
vite_preload()
Preloads a module for better performance. This is useful for code-split chunks that will be needed soon.
{{ vite_preload('components/Dashboard.ts') }}
Output:
<link rel="modulepreload" href="/assets/Dashboard-x9y8z7w6.js">
Typical Template Usage
Here's how assets are typically loaded in a UserFrosting template:
app/templates/content/scripts_site.html.twig:
{# Load site-wide JavaScript #}
{% block scripts_site %}
{{ vite_js('main.ts') }}
{% endblock %}
app/templates/content/stylesheets_site.html.twig:
{# Load site-wide CSS #}
{% block stylesheets_site %}
{{ vite_css('main.ts') }}
{% endblock %}
These blocks are then included in your base template:
app/templates/pages/abstract/base.html.twig:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block page_title %}{% endblock %}</title>
{# Include stylesheets #}
{% include 'content/stylesheets_site.html.twig' %}
</head>
<body>
<div id="app"></div>
{# Include scripts at end of body #}
{% include 'content/scripts_site.html.twig' %}
</body>
</html>
Loading Multiple Entry Points
If your application has multiple entry points, you can load them individually:
{# Load admin-specific assets #}
{% if is_admin %}
{{ vite_js('admin.ts') }}
{{ vite_css('admin.ts') }}
{% endif %}
{# Load main application assets #}
{{ vite_js('main.ts') }}
{{ vite_css('main.ts') }}
Make sure all entry points are defined in your vite.config.ts:
export default defineConfig({
build: {
rollupOptions: {
input: {
main: 'app/assets/main.ts',
admin: 'app/assets/admin.ts'
}
}
}
})
Static Assets
Static assets (images, fonts, etc.) should be placed in app/assets/public/. Vite will copy them to public/assets/ during the build.
Directory structure:
app/assets/
└── public/
├── images/
│ └── logo.png
└── fonts/
└── custom-font.woff2
Reference in templates:
<img src="/assets/images/logo.png" alt="Logo">
Reference in CSS/LESS:
.logo {
background-image: url('/assets/images/logo.png');
}
@font-face {
font-family: 'CustomFont';
src: url('/assets/fonts/custom-font.woff2');
}
Troubleshooting
Assets not loading
Symptom: 404 errors for asset files
Solutions:
- Development: Ensure Vite dev server is running (
php bakery assets:vite) - Production: Run
php bakery assets:build --production - Check that
assets.vite.devmatches your environment - Verify
assets.vite.serverpoints to the correct Vite server URL
Wrong assets loaded
Symptom: Old versions of assets are loaded
Solutions:
- Clear browser cache (Ctrl+Shift+R or Cmd+Shift+R)
- Check that manifest file exists:
public/assets/.vite/manifest.json - Rebuild assets:
php bakery assets:build --production - In development, restart Vite server
CORS errors in development
Symptom: CORS policy errors in browser console
Solutions:
- Ensure
server.origininvite.config.tsmatches the Vite server URL - Check that
assets.vite.serverin config matches the actual server - For Docker, ensure
server.host: trueis set in Vite config
Module not found
Symptom: Failed to resolve module specifier
Solutions:
- Ensure the file exists in
app/assets/ - Check the import path is relative or uses an alias
- Restart Vite dev server
- Clear Vite cache:
rm -rf node_modules/.vite
Next Steps
Learn about Advanced Usage including TypeScript, Vue components, preprocessors, and optimization techniques.