Converting a Laravel Inertia App from Mix to Vite

Laravel
16 July 2022 / 4 minute read

I recently converted my Inertia app from Laravel Mix to using Vite. In this post I'll talk about how it went, as well as some of the gotchas.

Initial Thoughts

I'd like to start off by saying I think the decision to move from Mix to Vite in a minor Laravel release (9.2.0) was a mistake.

Vite is very different from Mix in a lot of ways, and now any time someone makes a new Laravel app it's going to use Vite. It's going to be very jarring for a big part of community.

It's easy to forget the majority of everyday Laravel developers aren't on Twitter and "in" the community. They're trying to get their work done so they can home and enjoy their lives. I believe there's absolutely nothing wrong with that.


Jumping In Head First

When I saw Vite was going to be the default I was apprehensive, mainly because it was new, however I was more than willing to jump in head first.

I initially tried using Vite on my own a few weeks before Jess Archer did all the hard work getting the proper implementation done. I'll be honest, I struggled big time and gave up after about an hour of frustration.

However, thanks to Jess's hard work, it made my life a lot easier than it would've been!

Problems with Inertia

There's one major difference between Webpack and Vite that threw me a curve ball. It's that Vite doesn't support it when you use await import statements for your Inertia layouts, so the following code now longer works:

import { createInertiaApp } from '@inertiajs/inertia-vue3';

import UserLayout from './src/layouts/User';

createInertiaApp({
    resolve: async name => {
        let page = (await import(`./src/views/${name}`)).default;

        page.layout ??= UserLayout;

        return page;
    },
});

It needed to be changed to use the new laravel-vite-plugin, which helps with resolving the templates.

import { createInertiaApp } from '@inertiajs/inertia-vue3';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';

createInertiaApp({
    resolve: async name => {
        let page = resolvePageComponent(`./src/views/${name}.vue`, import.meta.glob('./src/views/**/*.vue'));

        return page;
    },
});

This created a problem because I can no longer specify the "default" page template for my Inertia pages. Now I have to manually specify it in every Vue page.

At first this bugged me, however I later realised it's actually better becuase the layout of the current page is no longer obscured while you're editing it.

import UserLayout from "@js/layouts/User.vue";

export default {
    layout: UserLayout,

    data() {
        return {
            title: "Dashboard",
        };
    },
};

Vue Imports and File Extensions

In my app I've got a lot of imports for things like components and layouts. This is just part of the development experience when it comes to building an SPA. The issue I ran into is that when compiling with Webpack, you can omit the .vue file extension, so you get something like this:

import Button from "@js/components/Button";

Unfortunately Vite doesn't like it when there's no file extension and will fall apart.

This isn't a criticism of Vite, I actually think having the file extensions makes a lot of sense, it's just a bad pattern I'd fallen into.

To fix the issue, you need to change every import to include the file extension, like so:

import Button from "@js/components/Button.vue";

Problems with Ziggy

Ziggy is a fantastic tool that helps you use Laravel defined routes in your JavaScript files. Incredibly useful when you're building and SPA (or whatever you'd call an Inertia app I suppose).

Unfortunately, the way I had Ziggy set up no longer worked with Vite.

I've written another post, Using Ziggy with Laravel, Inertia (Vue) and Vite, that deals with those issues. Be sure to check that out to see how I solved it.


Wrapping Up

Overall I'm very happy with Vite set up (once I got over the migration issues).

It's so fast it's honestly ridiculous. The way it achieves this is by not pre-compiling your JavaScript, like Webpack does, when you're in development mode. It only run all the minification and optimisation stuff when you build for production.

If you've recently moved to Vite from Mix and you're having issues, give me a shout on Twitter and maybe we can end up helping each other!