DEV Community

Halí
Halí

Posted on • Originally published at halivert.dev

6 4

Laravel routes in JavaScript

TL;DR With a Package
https://github.com/halivert/laravel-js-routes

We generally use JavaScript for the front-end in our applications, if we also use Laravel we notice that it includes a very useful wrapper called Laravel Mix, that can preprocess our JS files.

There's a problem when we want to get some Laravel route in any JS module. A naive approach is to export all our routes into a JSON and then use a function that has a similar behavior but in JS.

Code

That's why I crafted a Laravel command (usable with php artisan) composed by this code:

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Route;

class CreateJSRoutesCommand extends Command
{
    public function handle()
    {
      /*
       * When we call the command, this method executes 
       * first.
       */
    }

    public function createFile($fileName, $contents)
    {
      /*
       * This method creates a file with name equals to
       * $fileName and content equals to $contents, it also 
       * asks if you want to overwrite the file in case 
       * another with same name exists.
       */
    }

    private function includeRoute($value, $routeName)
    {
      /*
       * This function determines if a route must be included 
       * or not in our JSON, by default excludes telescope 
       * routes.
       */
    }

    public function getJSPath($path)
    {
      /*
       * This returns the route where our new file with JSON 
       * and function must be written.
       */
    }
}
Enter fullscreen mode Exit fullscreen mode

The handle function does most of the work, first we get Laravel routes, filter it and keep its URI.

$routes = collect(
    Route::getRoutes()->getRoutesByName()
  )->filter(function ($route, $key) {
    return $this->includeRoute($route, $key);
  })->map(function ($route) {
    return [
      'uri' => $route->uri
    ];
  });
Enter fullscreen mode Exit fullscreen mode

The content of our file will be composed of the JSON and function route so we start adding the var name and the content.

$jsonFlags = JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE;

$content = 'const routes = ';
$content .= json_encode($routes, $jsonFlags);
$content .= ";\n\n";
Enter fullscreen mode Exit fullscreen mode

Then we build the route function (it's on a separate file)

$content .= file_get_contents(
    __DIR__ . '/../assets/js/routeFunction.js'
);
Enter fullscreen mode Exit fullscreen mode
// assets/js/routeFunction.js

// This function receives as a route name and an array of
// parameters
const route = (routeName, params = []) => {
  // It searches in the stored routes one that match with the
  // given name and if it doesn't exists throws an error
  const _route = routes[routeName];
  if (_route == null) throw "Requested route doesn't exist";

  let uri = _route.uri;

  // If an URI is found, replace the parameters with a RegEx
  // (I don't know how I did it) and throws another error if
  // there are missing parameters. 
  // Remaining parameters will be ignored.

  const matches = uri.match(/{[\w]+}/g) || [];
  const requiredParametersCount = matches.length;

  if (params instanceof Array) {
    if (params.length < requiredParametersCount) throw "Missing parameters";

    for (let i = 0; i < requiredParametersCount; i++)
      uri = uri.replace(/{[\w]+}/, params.shift());

    for (let i = 0; i < params.length; i++)
      uri += (i ? "&" : "?") + params[i] + "=" + params[i];
  } else if (params instanceof Object) {
    let extraParams = matches.reduce((ac, match) => {
      let key = match.substring(1, match.length - 1);
      if (params.hasOwnProperty(key)) {
        uri = uri.replace(new RegExp(match, "g"), params[key]);
        delete ac[key];
      }
      return ac;
    }, params);

    Object.keys(extraParams).forEach((key, i) => {
      uri += (i ? "&" : "?") + key + "=" + extraParams[key];
    });
  }

  if (uri.includes("}")) throw "Missing parameters";

  return "/" + uri;
};

export { route };
Enter fullscreen mode Exit fullscreen mode

Finally we create the file.

$fileName = $this->option('name') ?? config('app.jsroutes.name');
if ($this->createFile($fileName, $content)) {
  $this->info("$fileName created");
}
Enter fullscreen mode Exit fullscreen mode

Installation

composer require halivert/laravel-js-routes
Enter fullscreen mode Exit fullscreen mode

Before use

If we already add the command to Laravel, then we execute it with

php artisan route:tojs
Enter fullscreen mode Exit fullscreen mode

Then we add the file to our webpack.mix.js file, so it can be processed.

mix.js("resources/js/routes", "public/js");
Enter fullscreen mode Exit fullscreen mode

And after a yarn prod or npm prod we can use our routes function when we want to call a route by its name in a JS file.

import { route } from "./routes.js";
Enter fullscreen mode Exit fullscreen mode

Use

Use examples:

axios
  .get(route("routeName", [param1, param2]))
  .then(response => {
    console.log(response.data);
  });
Enter fullscreen mode Exit fullscreen mode

I would love to read your comments
Happy coding! 👋

Sentry blog image

How I fixed 20 seconds of lag for every user in just 20 minutes.

Our AI agent was running 10-20 seconds slower than it should, impacting both our own developers and our early adopters. See how I used Sentry Profiling to fix it in record time.

Read more

Top comments (6)

Collapse
 
mahdipishguy profile image
Mahdi Pishguy • Edited

Hopefully topic and this tutorial was grate for me, thanks a lot :)

Collapse
 
halivert profile image
Halí

Thank you 😌

Collapse
 
seyid20 profile image
seyid20 • Edited

I was struggling with other similar product but when i get this my headache gone.
hoe can i use halivert/laravel-js-routes in larave version 7.x.x

Collapse
 
halivert profile image
Halí • Edited

Thanks for your comments, I appreciate them 😌🙏🏽

Also the package now depends on laravel/framework: 6, 7 or 8

Collapse
 
jinoantony profile image
Jino Antony

Good one. Does this generate a full URL or relative URL?

Collapse
 
halivert profile image
Halí

Thank you
The route generated is relative, for now

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay