I'm using VueJS. I have externally generated markdowns, and I want to generate static pages out of them thanks to a vue component. I'm using the vite-plugin-md
to convert imported md files into a component.
Config (vite.config.js
)
import Markdown from "vite-plugin-vue-markdown"
The router (index.ts
)
{
path: "/my_page_1",
name: "My Page 1",
component: () => import("@/pages/markdown.vue"),
}
The component (markdown.vue
)
<template>
<MardownPage/>
</template>
<script lang="ts" setup>
import MardownPage from "@/assets/markdown/my_page_1.md"
</script>
In the working example, the component is tied to a unique markdown.
I actually want to use the same component for many different markdown pages. I feel the expected way to do this is to have something like the following in the router :
{
path: "/my_page_1",
name: "My Page 1",
component: () => import("@/pages/markdown.vue"),
meta: {
path: "@/assets/markdown/page_1.md",
},
},
{
path: "/my_page_2",
name: "My Page 2",
component: () => import("@/pages/markdown.vue"),
meta: {
path: "@/assets/markdown/page_2.md",
},
}
On the component side, I've written the following
import {useRoute} from "vue-router";
import { defineAsyncComponent } from 'vue'
const route = useRoute();
console.log(route.meta.path);
const AsyncComp = defineAsyncComponent(() =>
import(route.meta.path)
)
While the path appears in the console, it does return an error related to the dynamic importation of the module (error loading dynamically imported module
).
I've tested many options related to lazy loading, dynamic routes, promises, ... (which I'm not 100% familiar and skilled with) but haven't worked my way around to do so.
Looking at what you currently have and what you described as the desired output, I would suggest starting at looking at defineAsyncComponent
. This function needs to be provided with a resolved promised. You are currently attempting to run import dynamically at runtime & it might also have something to do with aliases in your path.
I setup the following project:
vite.config.ts
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Markdown from 'vite-plugin-vue-markdown'
import path from 'node:path'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
include: [/\.vue$/, /\.md$/],
}),
Markdown(),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
'components': path.resolve(__dirname, './src/components'),
}
}
})
src/router/index.ts
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
// ...
{
path: '/test',
name: 'test',
component: () => import('@/views/MarkdownView.vue'),
meta: {
path: 'components/Test.md',
markdownComponent: defineAsyncComponent(() => import('components/Test.md'))
},
}
]
})
src/views/MarkdownView.vue
<template>
<AsyncMarkdown />
</template>
<script setup lang="ts">
import { defineAsyncComponent } from 'vue'
import { useRoute } from 'vue-router';
const route = useRoute()
console.log(route.meta.path) // components/Test.md
// DOES NOT WORK
const AsyncMarkdown = defineAsyncComponent(() => import(route.meta.path))
// WORKS
const AsyncMarkdown = route.meta.markdownComponent
</script>
If I change the route.meta.path
to the relative path ../components/Test.md
, it will then load the component.
defineAsyncComponent()
in your routerroute.meta.page
variable.