symfony/asset-mapper
Symfony AssetMapper exposes asset directories, copies them to a public folder with digested/versioned filenames, and can generate an importmap so you can use modern JavaScript modules without a build step.
## Getting Started
### Minimal Steps to Begin
1. **Installation**:
```bash
composer require symfony/asset-mapper
For Laravel, manually integrate the component or use Symfony’s AssetMapperBundle if available.
Configuration:
Create config/asset_mapper.php with basic settings:
return [
'source_dirs' => [
resource_path('assets'), // Source assets directory
],
'public_dir' => public_path('assets'), // Output directory
'version_strategy' => 'hash', // 'hash' or 'timestamp'
'import_map' => [
'entrypoints' => [
'app' => ['main.js'], // Entry points for importmap
],
],
];
First Command:
php artisan asset-map:dump
This generates versioned assets (e.g., main.[hash].js) and an importmap.json in the public directory.
Usage in Blade:
<!-- Versioned asset -->
<script type="module" src="{{ asset('assets/main.[hash].js') }}"></script>
<!-- Importmap for ES modules -->
<script type="importmap">
{
"imports": {
"lodash": "/assets/lodash.[hash].js",
"react": "https://esm.sh/react@18"
}
}
</script>
First Use Case:
Replace manual versioning (e.g., ?v=1.2) with auto-generated hashes for cache-busting. Enable ES modules for modern JavaScript without a build step.
config/asset_mapper.php: Central configuration for source directories, output paths, and versioning.asset-map:dump: Generate versioned assets and importmap.asset-map:watch: Auto-rebuild assets during development.public/assets/importmap.json: Auto-generated importmap for ES modules.version_strategy: 'hash' for production to ensure cache-busting filenames (e.g., styles.[hash].css).config/asset_mapper.php:
'version_strategy' => env('APP_ENV') === 'prod' ? 'hash' : 'timestamp',
// app/Helpers/AssetMapperHelper.php
function versioned_asset($path) {
$mapper = app(\Symfony\Component\AssetMapper\AssetMapper::class);
return $mapper->getUrl($path);
}
Usage:
<link rel="stylesheet" href="{{ versioned_asset('css/app.css') }}">
import_map to define entry points and external dependencies.config/asset_mapper.php:
'import_map' => [
'entrypoints' => [
'app' => ['main.js'],
'admin' => ['admin.js'],
],
'imports' => [
'lodash' => 'https://esm.sh/lodash@4.17.21',
],
],
AssetMapper service to generate the importmap dynamically in a controller:
use Symfony\Component\AssetMapper\AssetMapper;
use Symfony\Component\AssetMapper\ImportMap\ImportMap;
public function getImportmap(AssetMapper $mapper) {
$importMap = $mapper->getImportMap();
return response()->json($importMap->toArray());
}
asset-map:watchasset-map:watch for live reloading during development.php artisan asset-map:watch
config/asset_mapper.php:
'watch' => [
'patterns' => ['resources/assets/**/*'],
],
mix-manifest.json with the auto-generated importmap.json for ES modules.// app/Services/CustomVersionStrategy.php
use Symfony\Component\AssetMapper\VersionStrategy\VersionStrategyInterface;
class CustomVersionStrategy implements VersionStrategyInterface {
public function getVersion(string $path): string {
return filemtime($path);
}
}
config/asset_mapper.php:
'version_strategy' => \App\Services\CustomVersionStrategy::class,
asset-map:dump as a post-processing step for Laravel Mix or Vite.webpack.mix.js:
mix.postCss('resources/css/app.css', 'public/assets/css', [
// PostCSS config
])
.then(() => {
require('child_process').execSync('php artisan asset-map:dump');
});
vite.config.js:
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
plugins: [
laravel({
input: ['resources/js/app.js'],
refresh: true,
}),
],
build: {
rollupOptions: {
output: {
assetFileNames: 'assets/[name].[hash][extname]',
},
},
},
});
asset-map:dump after Vite builds:
npm run dev && php artisan asset-map:dump
@import and JSON imports.@import:
@import url('./variables.css');
import data from './data.json';
config/asset_mapper.php:
'import_map' => [
'entrypoints' => [
'app' => ['main.js'],
],
'imports' => [
'./data.json' => '/assets/data.[hash].json',
],
],
Missing or Incorrect Source Directories:
source_dirs is misconfigured.config/asset_mapper.php and ensure they exist:
'source_dirs' => [
resource_path('assets'), // Correct path
// base_path('vendor/foo/bar') // Example of external dependency
],
Circular Imports in CSS/JS:
--dry-run flag to debug:
php artisan asset-map:dump --dry-run
Importmap Polyfill Issues:
'import_map' => [
'polyfill' => false, // Disable if using a custom polyfill
],
Version Strategy Conflicts:
timestamp in production can break caching.hash in production:
'version_strategy' => env('APP_ENV') === 'prod' ? 'hash' : 'timestamp',
Duplicate Entries in Importmap:
composer update symfony/asset-mapper
Case Sensitivity in File Paths:
config/asset_mapper.php:
'source_dirs' => [
strtolower(resource_path('assets
How can I help you explore Laravel packages today?