Optimize Mermaid and blog component loading with lazy imports

This commit is contained in:
Michael Freno
2026-01-04 11:24:14 -05:00
parent 7e89e6dda2
commit 68073b4f17
9 changed files with 3300 additions and 30 deletions

View File

@@ -1,26 +1,30 @@
import { onMount } from "solid-js";
import mermaid from "mermaid";
mermaid.initialize({
startOnLoad: false,
theme: "dark",
securityLevel: "loose",
fontFamily: "monospace",
themeVariables: {
darkMode: true,
primaryColor: "#2c2f40",
primaryTextColor: "#b5c1f1",
primaryBorderColor: "#739df2",
lineColor: "#739df2",
secondaryColor: "#3e4255",
tertiaryColor: "#505469"
}
});
export default function MermaidRenderer() {
onMount(() => {
onMount(async () => {
const mermaidPres = document.querySelectorAll('pre[data-type="mermaid"]');
// Only load mermaid if there are diagrams to render
if (mermaidPres.length === 0) return;
const mermaid = (await import("mermaid")).default;
mermaid.initialize({
startOnLoad: false,
theme: "dark",
securityLevel: "loose",
fontFamily: "monospace",
themeVariables: {
darkMode: true,
primaryColor: "#2c2f40",
primaryTextColor: "#b5c1f1",
primaryBorderColor: "#739df2",
lineColor: "#739df2",
secondaryColor: "#3e4255",
tertiaryColor: "#505469"
}
});
mermaidPres.forEach(async (pre, index) => {
const code = pre.querySelector("code");
if (!code) return;

View File

@@ -1,6 +1,7 @@
import { createEffect, createSignal, onMount } from "solid-js";
import { createEffect, createSignal, onMount, lazy } from "solid-js";
import type { HLJSApi } from "highlight.js";
import MermaidRenderer from "./MermaidRenderer";
const MermaidRenderer = lazy(() => import("./MermaidRenderer"));
export interface PostBodyClientProps {
body: string;

View File

@@ -31,7 +31,7 @@ import { ConditionalInline } from "./extensions/ConditionalInline";
import TextAlign from "@tiptap/extension-text-align";
import Superscript from "@tiptap/extension-superscript";
import Subscript from "@tiptap/extension-subscript";
import mermaid from "mermaid";
import type { default as MermaidType } from "mermaid";
import css from "highlight.js/lib/languages/css";
import js from "highlight.js/lib/languages/javascript";
import ts from "highlight.js/lib/languages/typescript";
@@ -699,8 +699,14 @@ export default function TextEditor(props: TextEditorProps) {
let bubbleMenuRef!: HTMLDivElement;
let containerRef!: HTMLDivElement;
onMount(() => {
mermaid.initialize({
const [mermaid, setMermaid] = createSignal<typeof MermaidType | null>(null);
onMount(async () => {
// Lazy load mermaid only when editor is mounted
const mermaidModule = await import("mermaid");
const mermaidInstance = mermaidModule.default;
mermaidInstance.initialize({
startOnLoad: false,
theme: "dark",
securityLevel: "loose",
@@ -715,6 +721,8 @@ export default function TextEditor(props: TextEditorProps) {
tertiaryColor: "#505469"
}
});
setMermaid(() => mermaidInstance);
});
const [showBubbleMenu, setShowBubbleMenu] = createSignal(false);
@@ -1017,6 +1025,9 @@ export default function TextEditor(props: TextEditorProps) {
};
const validateAndPreviewMermaid = async (code: string) => {
const mermaidInstance = mermaid();
if (!mermaidInstance) return; // Wait for mermaid to load
if (!code.trim()) {
setMermaidValidation({ valid: true, error: null });
setMermaidPreviewSvg("");
@@ -1024,10 +1035,10 @@ export default function TextEditor(props: TextEditorProps) {
}
try {
await mermaid.parse(code);
await mermaidInstance.parse(code);
const id = `mermaid-preview-${Date.now()}`;
const { svg } = await mermaid.render(id, code);
const { svg } = await mermaidInstance.render(id, code);
setMermaidValidation({ valid: true, error: null });
setMermaidPreviewSvg(svg);

View File

@@ -1,11 +1,13 @@
import { Show } from "solid-js";
import { Show, lazy } from "solid-js";
import { query, redirect } from "@solidjs/router";
import { Title, Meta } from "@solidjs/meta";
import { createAsync } from "@solidjs/router";
import { getEvent } from "vinxi/http";
import PostForm from "~/components/blog/PostForm";
import { Spinner } from "~/components/Spinner";
import "../post.css";
const PostForm = lazy(() => import("~/components/blog/PostForm"));
const getAuthState = query(async () => {
"use server";
const { getPrivilegeLevel, getUserID } = await import("~/server/utils");
@@ -36,7 +38,7 @@ export default function CreatePost() {
content="Create a new blog post with rich text editing, image uploads, and tag management."
/>
<Show when={authState()?.userID}>
<Show when={authState()?.userID} fallback={<Spinner />}>
<PostForm mode="create" userID={authState()!.userID} />
</Show>
</>

View File

@@ -1,11 +1,12 @@
import { Show } from "solid-js";
import { Show, lazy } from "solid-js";
import { useParams, query } from "@solidjs/router";
import { Title, Meta } from "@solidjs/meta";
import { createAsync } from "@solidjs/router";
import { getEvent } from "vinxi/http";
import PostForm from "~/components/blog/PostForm";
import "../post.css";
const PostForm = lazy(() => import("~/components/blog/PostForm"));
const getPostForEdit = query(async (id: string) => {
"use server";
const { getPrivilegeLevel, getUserID, ConnectionFactory } =