Search code examples
vuejs3vue-routervitevue-router4

Unknown variable dynamic import


I have a vue 3 app with Vite and vue-router where I am using dyanmic imports to split routes for better organization. Here is the code.

router/index.ts

import { authenticatedRoutes,publicRoutes } from './routes'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: '/',
      name: 'home',
      component: AuthenticatedLayout,
      children:[
        ...authenticatedRoutes.map((item) => ({
          ...item,
          component: () => import(`../views/${item.component}/index.vue`)
        }))
      ]
    },
    ...publicRoutes.map((item) => ({
      ...item,
      component: () => import(`../src/views/${item.component}/index.vue`)
    }))
  ]
})

router/routes.js

export const authenticatedRoutes = [
    {
        path: '/',
        name: 'home',
        component: 'home',
    }
]

export const publicRoutes = [
    {
        path: '/test',
        name: 'material-design2',
        component: 'test/test2'
    }

Now I want to create a structure where I can go n-Level deep in routes structure so they are organized, the component here specifies the directories path with this we can have as much directory nesting as we can.

Now the problem is Vite throws an error

Unknown variable dynamic import: ../src/views/test/test2/index.vue

Now I know Vite only handles dynamic importing upto one level as mentioned in the documentation here To handle this I tried the / import method

component: () => import(`/src/views/${item.component}/index.vue`)

that ended up working locally but crashed on production build its also mentioned in documentation here which says you can only import with ./ or ../

Is there a way to achieve this architecture using Vite? I know this works with webpack since I used this before.


Solution

  • Bad practice:

    // provide a exact file Level but not n-Level
    const modules = import.meta.glob("../views/**/**/**/**/index.vue");
    routes: [
    {
      path: '/',
      name: 'home',
      component: AuthenticatedLayout,
      children:[
        ...authenticatedRoutes.map((item) => ({
          ...item,
          component: modules[`../views/${item.component}/index.vue`]
        }))
      ]
    },
    

    Best practice:

    export const authenticatedRoutes = [
    {
        path: '/',
        name: 'home',
        component: () => import(`../views/home/index.vue`) 
    }
    ]
    

    ...

        routes: [
    {
      path: '/',
      name: 'home',
      component: AuthenticatedLayout,
      children:authenticatedRoutes
    },