title: Vue 3 dynamic components at router level
body: <p>Dynamic imports is needed for me, eg. i have 10 layouts, but user only visited 3 layouts, I should not import all of the layouts, since its consumed unnecessary resources.</p>
  <p>Since its dynamic import, each time i switch between Login &amp; Register path <code>&lt;RouterLink :to&quot;{name: 'Login'}&quot; /&gt;</code> &amp; <code>&lt;RouterLink :to&quot;{name: 'Register'}&quot; /&gt;</code>, I got rerender or dynamic import the layout again.</p>
  <p>My question is what is the better way to handle it, without rerender or dynamic import the layout again? Or can I save the dynamic import component into the current vue 3 context?</p>
  <p><strong>App.vue</strong> this is my app with watching the router and switch the layout based on route.meta.layout</p>
  <pre class="lang-js prettyprint-override"><code>&lt;template&gt;
    &lt;component :is=&quot;layout.component&quot; /&gt;
  &lt;/template&gt;
  
  &lt;script&gt;
  import DefaultLayout from &quot;./layout/default.vue&quot;;
  
  import {
    ref,
    shallowRef,
    reactive,
    shallowReactive,
    watch,
    defineAsyncComponent,
  } from &quot;vue&quot;;
  
  import { useRoute } from &quot;vue-router&quot;;
  
  export default {
    name: &quot;App&quot;,
    setup(props, context) {
      const layout = shallowRef(DefaultLayout);
      const route = useRoute();
      watch(
        () =&gt; route.meta,
        async (meta) =&gt; {
          if (meta.layout) {
            layout = defineAsyncComponent(() =&gt;
              import(`./layout/${meta.layout}.vue`)
            );
          } else {
            layout = DefaultLayout;
          }
        },
        { immediate: true }
      );
      return { layout };
    },
  };
  &lt;/script&gt;
  </code></pre>
  <p><strong>router/index.js</strong> this is my router with layout meta</p>
  <pre class="lang-js prettyprint-override"><code>import { createRouter, createWebHistory } from &quot;vue-router&quot;;
  import Home from &quot;@/views/Home.vue&quot;;
  import NotFound from &quot;@/views/NotFound.vue&quot;;
  
  const routes = [
    {
      path: &quot;/&quot;,
      name: &quot;Home&quot;,
      component: Home,
    },
    {
      path: &quot;/login&quot;,
      name: &quot;Login&quot;,
      meta: {
        layout: &quot;empty&quot;,
      },
      component: function () {
        return import(/* webpackChunkName: &quot;login&quot; */ &quot;../views/Login.vue&quot;);
      },
    },
    {
      path: &quot;/register&quot;,
      name: &quot;Register&quot;,
      meta: {
        layout: &quot;empty&quot;,
      },
      component: function () {
        return import(/* webpackChunkName: &quot;register&quot; */ &quot;../views/Register.vue&quot;);
      },
    },
    { path: &quot;/:pathMatch(.*)&quot;, component: NotFound },
  ];
  
  const router = createRouter({
    history: createWebHistory(import.meta.env.VITE_GITLAB_BASE_PATH),
    routes,
    scrollBehavior(to, from, savedPosition) {
      // always scroll to top
      return { top: 0 };
    },
  });
  
  export default router;
  </code></pre>