Introduction
Beyond the basics, Vite supports static asset imports, code splitting, path aliases, framework plugins (React/Vue), environment variables, and SSR — everything you need for a non-trivial frontend.
Key Concepts
- Static asset import: Referencing images/fonts from CSS or JS. Vite rewrites URLs to their hashed production paths at build time.
- Dynamic import:
import('module')— Vite splits the imported module into a separate chunk loaded on demand. - Path alias: A shorthand defined in
resolve.alias(e.g.,@ → resources/js) that simplifies deep imports. - Framework plugin:
@vitejs/plugin-reactor@vitejs/plugin-vue— adds JSX/SFC support and enables Fast Refresh. VITE_env vars: Environment variables prefixed withVITE_that Vite exposes to client-side code viaimport.meta.env.
Real World Context
When your frontend grows beyond a single bundle, these features keep it fast and maintainable. A well-configured Vite setup lazy-loads heavy dependencies, aliases common paths, and surfaces environment values without leaking server secrets.
Deep Dive
Master advanced Vite features for complex Laravel applications.
Static Asset Handling
Images and Fonts
Reference assets in CSS:
css/* resources/css/app.css */ .hero { background-image: url('../images/hero.jpg'); } @font-face { font-family: 'CustomFont'; src: url('../fonts/CustomFont.woff2') format('woff2'); }
Reference in JavaScript:
javascript// resources/js/app.js import logoUrl from '../images/logo.svg'; document.getElementById('logo').src = logoUrl;
Asset Helper in Blade
blade{{-- For images in public folder --}} <img src="{{ asset('images/logo.png') }}" alt="Logo"> {{-- For Vite-processed assets (recommended) --}} <img src="{{ Vite::asset('resources/images/logo.svg') }}" alt="Logo">
Code Splitting
Vite automatically splits code for optimal loading:
javascript// Dynamic import for code splitting const loadChart = async () => { const { Chart } = await import('chart.js'); return Chart; }; // Use when needed document.getElementById('show-chart').addEventListener('click', async () => { const Chart = await loadChart(); // Initialize chart });
Alias Configuration
javascript// vite.config.js import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import path from 'path'; export default defineConfig({ plugins: [ laravel({ input: ['resources/css/app.css', 'resources/js/app.js'], refresh: true, }), ], resolve: { alias: { '@': path.resolve(__dirname, 'resources/js'), '@components': path.resolve(__dirname, 'resources/js/components'), '@utils': path.resolve(__dirname, 'resources/js/utils'), }, }, });
Usage:
javascript// Instead of: import { helper } from '../../utils/helper' import { helper } from '@utils/helper'; import Button from '@components/Button';
React Integration
bashnpm install react react-dom @vitejs/plugin-react
javascript// vite.config.js import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import react from '@vitejs/plugin-react'; export default defineConfig({ plugins: [ laravel({ input: ['resources/css/app.css', 'resources/js/app.jsx'], refresh: true, }), react(), ], });
jsx// resources/js/app.jsx import '../css/app.css'; import { createRoot } from 'react-dom/client'; import App from './components/App'; const container = document.getElementById('app'); const root = createRoot(container); root.render(<App />);
blade{{-- In Blade --}} <!DOCTYPE html> <html> <head> @viteReactRefresh @vite(['resources/css/app.css', 'resources/js/app.jsx']) </head> <body> <div id="app"></div> </body> </html>
Vue Integration
bashnpm install vue @vitejs/plugin-vue
javascript// vite.config.js import { defineConfig } from 'vite'; import laravel from 'laravel-vite-plugin'; import vue from '@vitejs/plugin-vue'; export default defineConfig({ plugins: [ laravel({ input: ['resources/css/app.css', 'resources/js/app.js'], refresh: true, }), vue({ template: { transformAssetUrls: { base: null, includeAbsolute: false, }, }, }), ], });
javascript// resources/js/app.js import '../css/app.css'; import { createApp } from 'vue'; import App from './components/App.vue'; createApp(App).mount('#app');
Environment Variables
Access environment variables in JavaScript:
env# .env VITE_APP_NAME="My App" VITE_API_URL="https://api.example.com"
javascript// Must be prefixed with VITE_ console.log(import.meta.env.VITE_APP_NAME); console.log(import.meta.env.VITE_API_URL); // Built-in variables console.log(import.meta.env.MODE); // 'development' or 'production' console.log(import.meta.env.DEV); // true in development console.log(import.meta.env.PROD); // true in production
Custom Blade Refresh
javascript// vite.config.js export default defineConfig({ plugins: [ laravel({ input: ['resources/css/app.css', 'resources/js/app.js'], refresh: [ 'resources/views/**', 'routes/**', 'app/View/Components/**', ], }), ], });
SSR Support
For server-side rendering:
javascript// vite.config.js export default defineConfig({ plugins: [ laravel({ input: 'resources/js/app.js', ssr: 'resources/js/ssr.js', refresh: true, }), ], });
Subresource Integrity (SRI)
php// In AppServiceProvider boot() use Illuminate\Support\Facades\Vite; Vite::useIntegrityKey('custom-integrity'); // Or disable Vite::useIntegrityKey(false);
Prefetching
php// Prefetch assets for faster navigation Vite::prefetch(concurrency: 3);
Common Pitfalls
- Forgetting the
VITE_prefix on env vars — Any other prefix is invisible toimport.meta.envfor security reasons. - Importing unused dependencies — A single
import { everything } from 'lodash'can add 70 KB to your bundle. Use named imports orlodash-es. - Missing
@viteReactRefreshfor React — Fast Refresh won't work without this Blade directive in the layout.
Best Practices
- Use path aliases for deep imports —
@components/Buttonbeats../../components/Button. - Lazy-load large dependencies with dynamic imports — Chart libraries, map libraries, WYSIWYG editors should only load when the feature is actually used.
- Keep env vars strictly prefixed —
VITE_for client, everything else stays server-side.
Summary
- Import static assets directly from CSS or JS; Vite rewrites URLs at build time.
- Dynamic
import()calls produce code-split chunks. - Path aliases simplify deep imports via
resolve.alias. @vitejs/plugin-reactand@vitejs/plugin-vueenable JSX/SFC support.- Environment variables prefixed with
VITE_are exposed viaimport.meta.env. - Vite supports SSR builds and subresource integrity for advanced setups.