cdruc

Serve Vue3 applications using Laravel Valet

As many of you may know, if you're on a Mac, you can use Laravel Valet to quickly serve Laravel applications using the directory name as the hostname.

Now, I'm not in the business of wasting your time, so I'll say this from the start: this solution will not work with hot module replacement; it only works with a production bundle. However, the good news is we can still watch for changes and automatically trigger rebuilds.

Anyway, here's how you can do it.

The first thing you need to do is create a custom Laravel Valet driver. ~/.config/valet/Drivers/SampleValetDriver.php provides a great starting point, so duplicate that file to Vue3ValetDriver.php, open it, and make the following changes.

<?php

class Vue3ValetDriver extends ValetDriver
{
    public function serves($sitePath, $siteName, $uri)
    {
        return file_exists($sitePath.'/vite.config.js') && file_exists($sitePath.'/index.html');
    }

    public function isStaticFile($sitePath, $siteName, $uri)
    {
        if (file_exists($staticFilePath = $sitePath.'/dist/'.$uri)) {
            return $staticFilePath;
        }

        return false;
    }

    public function frontControllerPath($sitePath, $siteName, $uri)
    {
        return $sitePath.'/dist/index.html';
    }
}

The serves function determines whether or not the directory is a Vue3 application. It does that by checking the presence of the vite.config.js and index.html files. If both files are present, Valet will serve the directory using this new driver.

The isStaticFile determines if the incoming request is for a static file from the dist/ directory, and if it is, it returns a full path to it.

Finally, the frontControllerPath points to the entry file of our application, which for a Vue3 app is /dist/index.html.

Once you save the new driver, you need to make sure Laravel Valet serves the Vue3 application. You can move the Vue3 app inside a parked directory or run the valet link project-name command.

If you visit project-name.test and you get an error saying "Failed opening required... bla bla bla, /dist/index.html", that's because your Vue3 project doesn't have a production bundle yet (/dist directory). So create one using npm run build, refresh the page, and you should see your Vue3 app.

Valet serving Vue3 app

However, if you are to make some changes and hit save, the changes won't be reflected in the browser - even if you refresh the page.

You can't just run npm run dev because this won't update the dist directory with a new bundle; only npm run build does that. But then again, manually running npm run build every time we make a change doesn't sound that great either.

What you can do is create a new build-watch script that runs vite build but with a --watch flag included. This will make it so vite rebuilds the /dist directory every time you make changes to your application.

"build-watch": "vite build --watch"

Now you can run the new command npm run build-watch, and if you make a change, save, and refresh, the browser will reflect your changes.

PS: If you find a way to do this with HMR, please let me know!