Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

juriactes's avatar

Inertia test fails : Unable to locate file in Vite manifest

We have lots of pages tested that cause no issue. However, one of them is failing with the mesage: Unable to locate file in Vite manifest: resources/js/Pages/Shared/MainDashboardPage.vue

We of course properly generate the manifest using npm run build before running the tests (other tests are passing).

The browser properly displays the page as expected and it is all working nicely. Just the test is failing.

The test code is very simple:

        $this
            ->actingAs($user)
            ->get(route('shared.dashboard'))
            ->assertInertia(
                fn(Assert $page) => $page->component('Shared/MainDashboardPage')
            );

The page component is rather simple too:

<script lang="ts" setup>
//...
import WidgetContainer from "@/Components/Widgets/WidgetContainer.vue";
//...
</script>
<template>
    <!-- ... -->
        <template #content>
            <WidgetContainer :widgets="widgets" class="py-12" />
        </template>
    <!-- ... -->
</template>

Here is the manifest that gets generated (just the relevant lines):

  "resources/js/app.js": {
    "file": "assets/app.ed5c06ed.js",
    "src": "resources/js/app.js",
    "isEntry": true,
    "dynamicImports": [
      // ...
      "resources/js/Pages/Shared/ChangeLogPage.vue",
      "_MainDashboardPage.7e31d2a9.js"
    ],

  "_MainDashboardPage.7e31d2a9.js": {
    "file": "assets/MainDashboardPage.7e31d2a9.js",
    "isDynamicEntry": true,
    "imports": [
      "resources/js/app.js",
      "_AppLayout.vue_vue_type_script_setup_true_lang.85bb1e31.js",
      "_SimplePageHeading.571b4474.js",
      "_PageSectionHeading.32ec8671.js"
    ],
    "dynamicImports": [
      "resources/js/Components/Widgets/MultipleValuesWidget.vue",
      "resources/js/Components/Widgets/SingleValueWidget.vue",
      "resources/js/Components/Widgets/WidgetContainer.vue"
    ]
  },

  "resources/js/Components/Widgets/WidgetContainer.vue": {
    "file": "assets/WidgetContainer.c24f0198.js",
    "src": "resources/js/Components/Widgets/WidgetContainer.vue",
    "isDynamicEntry": true,
    "imports": [
      "_MainDashboardPage.7e31d2a9.js",
      "resources/js/app.js",
      "_AppLayout.vue_vue_type_script_setup_true_lang.85bb1e31.js",
      "_use-root-containers.90abfc39.js",
      "_HorizontalLogo.vue_vue_type_script_setup_true_lang.375eb4a2.js",
      "_XMarkIcon.59af79c0.js",
      "_SimplePageHeading.571b4474.js",
      "_PageSectionHeading.32ec8671.js"
    ],
    "css": [
      "assets/app.186a85dc.css"
    ]
  },

If we remove the WidgetContainer component from the MainDashboardPage (both the import and the usage in the template), then build the manifest and run the test, the test goes green. and the manifest properly gets an entry for that page:

  "resources/js/app.js": {
    "file": "assets/app.ed5c06ed.js",
    "src": "resources/js/app.js",
    "isEntry": true,
    "dynamicImports": [
      // ...
      "resources/js/Pages/Shared/ChangeLogPage.vue",
      "resources/js/Pages/Shared/MainDashboardPage.vue"
    ],

Here is the WidgetContainer component: we dynamically import other components (this is driven by PHP):

<script lang="ts" setup>
import { computed, defineAsyncComponent } from "vue";
import { trans } from "laravel-vue-i18n";

interface Props {
    widgets: object;
}

const props = defineProps<Props>();

const WidgetComponents = computed(() => {
    let out = {};

    for (const group in props.widgets) {
        for (const key in props.widgets[group]) {
            const w = props.widgets[group][key];
            out[w.component] = defineAsyncComponent(() => import(`../../Components/Widgets/${w.component}.vue`));
        }
    }
    return out;
});

</script>
<template>
    <template v-for="(group, groupId) in props.widgets" :key="groupId">
        <div class="grid grid-cols-1 gap-4 md:grid-cols-2 lg:grid-cols-4">
            <template v-for="(widget, key) in group" :key="key">
                <div :class="['mx-4 md:mx-0', colSpan(widget.colSpan), rowSpan(widget.rowSpan)]">
                    <component :is="WidgetComponents[widget.component]" :data="widget.data" :col-span="widget.colSpan" :row-span="widget.rowSpan" />
                </div>
            </template>
        </div>
    </template>
</template>

How can we get the manifest to properly include the MainDashboardPage?

0 likes
1 reply
LaryAI's avatar
Level 58

The issue seems to be related to the dynamic import of the WidgetContainer component in the MainDashboardPage component. The Vite manifest is not properly including the MainDashboardPage component because it is not able to resolve the dynamic import.

To fix this issue, you can try using the import.meta.glob function provided by Vite to dynamically import the components. Here's how you can modify the WidgetComponents computed property in the WidgetContainer component:

const WidgetComponents = computed(() => {
    let out = {};

    for (const group in props.widgets) {
        for (const key in props.widgets[group]) {
            const w = props.widgets[group][key];
            out[w.component] = defineAsyncComponent(() => import.meta.glob(`../../Components/Widgets/${w.component}.vue`));
        }
    }
    return out;
});

By using import.meta.glob, Vite will be able to properly resolve the dynamic imports and include the MainDashboardPage component in the Vite manifest.

Make sure to rebuild the manifest using npm run build after making this change and then run the test again to see if it passes.

Please or to participate in this conversation.