You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在SvelteKit中动态渲染数据库存储的MDX内容?

SvelteKit + SQLite3 动态渲染数据库中MDX内容的解决方案

问题核心

你当前方案的失效原因很直接:

  • Svelte编译出的JS是组件的运行时逻辑代码,{@html}只能渲染静态HTML,根本不会执行这些JS,自然无法渲染<Chart />这类Svelte组件。
  • mdsvex的用法有误,不需要嵌套调用preprocess: mdsvex(),mdsvex自身的compile方法就可以直接完成MDX到Svelte代码的转换。

可行解决方案(客户端动态渲染)

1. 调整服务端:只做MDX到Svelte的转换

服务端只负责把MDX转成标准Svelte代码,不做后续JS编译,把结果传给客户端处理:

/src/routes/test/+page.server.ts

import type { PageServerLoad } from "./$types"
import { compile } from "mdsvex";

export const load: PageServerLoad = async () => {
  const source = `
        <script>
          import Chart from '$lib/components/Chart.svelte';
        </script>
        
        # Hello friends
        
        <Chart />
        `;
  // MDX 直接编译为 Svelte 代码
  const { code: svelteCode } = await compile(source, {
    extensions: ['.mdx', '.svx'],
  });
  
  return { svelteCode };
}

2. 客户端:动态编译并挂载组件

在客户端用Svelte编译器处理服务端传来的Svelte代码,实例化组件并挂载:

/src/routes/test/+page.svelte

<script lang="ts">
    import { compile } from 'svelte/compiler';
    import { onMount } from 'svelte';
    export let data;

    let container: HTMLElement;

    onMount(async () => {
        if (!container || !data.svelteCode) return;

        // 编译Svelte代码为可执行模块
        const result = compile(data.svelteCode, {
            generate: 'dom',
            format: 'esm'
        });

        // 动态导入编译后的组件
        const module = await import(`data:text/javascript,${encodeURIComponent(result.js.code)}`);
        const Component = module.default;

        // 将组件挂载到页面容器
        new Component({
            target: container,
            props: {}
        });
    });
</script>

<div bind:this={container}></div>

生产环境优化方案

如果MDX内容较多,客户端编译会拖慢性能,建议在服务端完成全流程编译,把可执行的JS组件代码存在数据库,客户端直接加载:

服务端预编译全流程

/src/routes/test/+page.server.ts

import type { PageServerLoad } from "./$types"
import { compile as mdsvexCompile } from "mdsvex";
import { compile as svelteCompile } from 'svelte/compiler';

export const load: PageServerLoad = async () => {
  const source = `
        <script>
          import Chart from '$lib/components/Chart.svelte';
        </script>
        
        # Hello friends
        
        <Chart />
        `;
  // MDX -> Svelte
  const { code: svelteCode } = await mdsvexCompile(source, {
    extensions: ['.mdx', '.svx'],
  });

  // Svelte -> 可执行ESM代码
  const { js } = svelteCompile(svelteCode, { 
    generate: 'dom',
    format: 'esm',
    filename: 'dynamic-post.mdx'
  });
  
  return { componentCode: js.code };
}

客户端直接加载组件

/src/routes/test/+page.svelte

<script lang="ts">
    import { onMount } from 'svelte';
    export let data;

    let container: HTMLElement;

    onMount(async () => {
        if (!container || !data.componentCode) return;

        // 直接导入预编译好的组件代码
        const module = await import(`data:text/javascript,${encodeURIComponent(data.componentCode)}`);
        const Component = module.default;

        new Component({
            target: container,
            props: {}
        });
    });
</script>

<div bind:this={container}></div>

内容的提问来源于stack exchange,提问作者Joey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:25:13