friendsofsymfony/jsrouting-bundle
Installation:
composer require friendsofsymfony/jsrouting-bundle
Enable the bundle in config/bundles.php:
return [
// ...
FriendsOfSymfony\JsRoutingBundle\FriendsOfSymfonyJsRoutingBundle::class => ['all' => true],
];
Generate Routes:
Add the fos_js_routing Twig extension to your base template (e.g., base.html.twig):
{{ fos_js_routing(
routes|default([]),
callback|default('fos.Router.setData'),
json_encode|default(true),
minify|default(true),
ignore_missing|default(false)
) }}
Ensure routes is an array of route names (e.g., ['app_home', 'app_profile']).
First Use Case: Use the generated JavaScript in your frontend to dynamically build URLs:
// Example: Fetch a route URL with parameters
const url = fos.Router.generate('app_profile', { id: 123 });
fos_js_routing for template integration.fos.Router for client-side URL generation.config/packages/fos_js_routing.yaml for customization (e.g., route filtering, JSON encoding).Expose Routes:
Pass route names to fos_js_routing in Twig:
{{ fos_js_routing(['app_home', 'app_edit_profile']) }}
This renders a <script> tag with serialized route data.
Client-Side Usage:
Use fos.Router in JavaScript to generate URLs:
// Generate a URL with parameters
const profileUrl = fos.Router.generate('app_profile', { id: user.id });
// Handle dynamic links (e.g., in React/Vue)
<a href={fos.Router.generate('app_home')}>Home</a>
Dynamic Route Filtering: Filter routes server-side via configuration:
# config/packages/fos_js_routing.yaml
fos_js_routing:
routes_to_expose: [app_home, app_profile]
routes_to_expose_pattern: '/^app_' # Regex filter
SPAs (React/Vue/Angular):
Inject the fos.Router globally or pass it via context/API:
// Example: Vue.js
export default {
mounted() {
window.fos.Router.setData(JSON.parse(document.getElementById('fos-js-routing-data').textContent));
}
}
API-Driven Frontends:
Fetch routes via a dedicated endpoint (e.g., /api/routes) if using headless Symfony:
// src/Controller/RouteController.php
public function getRoutes(): JsonResponse
{
return $this->json($this->get('router')->getRouteCollection()->getRoutes());
}
Lazy Loading: Load routes asynchronously for large applications:
async function loadRoutes() {
const response = await fetch('/api/routes');
const routes = await response.json();
fos.Router.setData(routes);
}
Testing:
Mock fos.Router in tests:
// Jest example
global.fos = { Router: { generate: jest.fn(() => '/mock-url') } };
Route Name Mismatches:
fos.Router.generate('nonexistent_route') errors.{{ dump(router.getRouteCollection()) }} in Twig to list all routes.Caching Headaches:
php bin/console cache:clear
minify: false in development to avoid cached minified JS breaking changes.Parameter Validation:
fos.Router.generate() fails silently if parameters don’t match route requirements.try/catch:
try {
const url = fos.Router.generate('app_profile', { id: 'invalid' });
} catch (e) {
console.error('Invalid parameters:', e);
}
Twig Autoescape:
fos_js_routing may break if Twig autoescape is enabled.{# ... #}
{% autoescape false %}
{{ fos_js_routing(routes) }}
{% endautoescape %}
Inspect Generated JS:
View the rendered <script> tag in the browser’s DevTools to verify route data:
// Check if routes are loaded
console.log(fos.Router.getRoutes());
Symfony Debug Toolbar: Use the Router tab to validate route names and parameters.
Log Missing Routes:
Enable logging for missing routes in config/packages/fos_js_routing.yaml:
fos_js_routing:
ignore_missing: false # Default: true (silent failure)
Custom Route Data: Extend route data with metadata (e.g., permissions):
{{ fos_js_routing(routes, 'customCallback', true, true, false) }}
// Override the default callback
function customCallback(data) {
data.routes.forEach(route => {
route.metadata = { requiresAuth: true };
});
fos.Router.setData(data);
}
Webpack/Encore Integration: Process the JS routing file through Webpack:
// webpack.config.js
Encore
.addEntry('app', './assets/js/app.js')
.copyFiles({
from: './vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js/router.js',
to: 'js/[name].[hash].js'
});
Server-Side Route Filtering: Create a custom route collector to filter routes dynamically:
// src/Service/CustomRouteCollector.php
use Symfony\Component\Routing\RouteCollection;
class CustomRouteCollector {
public function filterRoutes(RouteCollection $collection): array {
return iterator_to_array(
$collection->filter(function ($name) {
return str_starts_with($name, 'app_');
})
);
}
}
Use it in Twig:
{{ fos_js_routing(app.service('custom_route_collector').filterRoutes(router.getRouteCollection())) }}
Minification: Enable minification in production:
{{ fos_js_routing(routes, null, true, true) }}
This reduces payload size by ~30%.
Selective Route Exposure: Expose only the routes needed by the current page:
{% block javascripts %}
{{ fos_js_routing(['app_home', 'app_current_page_route']) }}
{% endblock %}
HTTP/2 Server Push: Preload the routing JS file:
location / {
add_header Link "</js/router.min.js>; rel=preload; as=script";
}
How can I help you explore Laravel packages today?