funddy/jsrouting-bundle
Funddy JSRoutingBundle exposes Symfony routes to JavaScript, letting front-end code generate URLs from route names and parameters without hardcoding paths. It integrates with Symfony routing and provides a lightweight JS helper for client-side links, AJAX calls, and navigation.
Before anything else: this is a Symfony2 bundle, not a Laravel package. There is no service provider, no auto-discovery, no config/app.php entry. If you are coming from Laravel, the closest mental model is Tighten's Ziggy — it exposes named routes to JavaScript so you stop hand-concatenating URLs in front-end code. The concept transfers; the code does not. Expect to do the wiring the Symfony2 way (AppKernel + routing.yml).
Minimal steps:
composer require funddy/jsrouting-bundle. Pin the constraint and check it against your Symfony version first — a 5-star, zero-dependent bundle from the Symfony2 era is almost certainly capped at symfony/symfony ~2.x. On Symfony 4+ this will not resolve without a fork.app/AppKernel.php:
new Funddy\JsRoutingBundle\FunddyJsRoutingBundle(),
app/config/routing.yml:
funddy_js_routing:
resource: "@FunddyJsRoutingBundle/Resources/config/routing.xml"
Where to look first: the bundle's controller that serves the JS payload, the Resources/config/routing.xml (to confirm the route name and URL pattern), and the generated output itself — open it in the browser and read it. That file answers 90% of the questions you will have about what the runtime API actually looks like, which matters here because the public surface is thin and under-documented.
Expose routes explicitly, at the route definition. Whether via options: { expose: true } in routing.yml or the equivalent annotation default, exposure is opt-in. Resist the temptation to expose everything — see the performance note below.
Call by route name, not by URL string. The whole point:
// before
fetch('/admin/users/' + id + '/edit');
// after
fetch(Routing.generate('admin_user_edit', { id: id }));
Treat route names as the contract between back end and front end. When a route's path changes, the JS keeps working; that is the entire return on investment.
Prefer data attributes for the first paint. Anything already rendered server-side (form actions, links, pagination) should stay in Twig and be read out of data-* attributes. Use JS routing for the dynamic fragments — modals, async table rows, post-submit redirects — where no server-rendered element exists to hang a URL on.
Namespace route names in a small JS wrapper. Route names live as free-floating strings, so typos are silent until a user clicks. A thin module with an explicit ROUTES constant map — generated from a manifest or written by hand — turns runtime failures into a single place to audit and grep.
Version the generated payload. Serve the dump as a cacheable asset with a build hash or Symfony asset version in the URL, so a route change invalidates browsers. This is the single biggest operational win over regenerating per request.
Locale and parameters. If your app is localized, the locale is usually a route parameter; pass it explicitly rather than assuming the JS bundle silently inherits the server session's locale. Verify this in the dumped output before you rely on it.
\d+, slugs) are not validated client-side the way they are server-side. A numeric ID formatted as a string can produce a subtly wrong URL that 404s only in production.app/console cache:clear after route changes, and a browser cache bust on the generated JS. Forgetting the second is the classic "it works on my machine" report./app behind a load balancer, confirm whether generated URLs are absolute or root-relative. Absolute URLs baked from the request host will break behind a proxy unless trusted proxies are configured.routing.yml against the dumped JS rather than reading the bundle source. The dump is the ground truth of what the browser has.How can I help you explore Laravel packages today?