From c0b4bad93deb77ce560ff7b61d1a1b61a2bbe9db Mon Sep 17 00:00:00 2001 From: Michael Freno Date: Sun, 4 Jan 2026 21:40:27 -0500 Subject: [PATCH] new tests and bundling changes --- app.config.ts | 20 ++++++- src/components/blog/PostBodyClient.tsx | 82 +------------------------- src/components/blog/TextEditor.tsx | 64 +------------------- src/lib/highlight-bundle.ts | 72 ++++++++++++++++++++++ src/lib/lowlight-bundle.ts | 66 +++++++++++++++++++++ test-prod-server.mjs | 62 +++++++++++++++++++ 6 files changed, 221 insertions(+), 145 deletions(-) create mode 100644 src/lib/highlight-bundle.ts create mode 100644 src/lib/lowlight-bundle.ts create mode 100644 test-prod-server.mjs diff --git a/app.config.ts b/app.config.ts index 334fdd0..bb795fb 100644 --- a/app.config.ts +++ b/app.config.ts @@ -8,10 +8,26 @@ export default defineConfig({ rollupOptions: { output: { manualChunks: (id) => { - // Split highlight.js into its own chunk - if (id.includes("highlight.js")) { + // Bundle highlight.js and lowlight together + if (id.includes("highlight.js") || id.includes("lowlight")) { return "highlight"; } + + // Bundle Mermaid separately (large library, only used on some posts) + if (id.includes("mermaid")) { + return "mermaid"; + } + + // Bundle all Tiptap extensions together (only used in editor) + if (id.includes("@tiptap") || id.includes("solid-tiptap")) { + return "tiptap"; + } + + // Bundle motion libraries + if (id.includes("motion") || id.includes("@motionone")) { + return "motion"; + } + // Split other large vendor libraries if (id.includes("node_modules")) { // Keep all solid-related packages together to avoid circular deps diff --git a/src/components/blog/PostBodyClient.tsx b/src/components/blog/PostBodyClient.tsx index f8dbfdc..10a9f90 100644 --- a/src/components/blog/PostBodyClient.tsx +++ b/src/components/blog/PostBodyClient.tsx @@ -9,87 +9,7 @@ export interface PostBodyClientProps { } async function loadHighlightJS(): Promise { - const [ - hljsModule, - javascript, - typescript, - python, - rust, - c, - cpp, - csharp, - ocaml, - lua, - swift, - bash, - css, - xml, // handles HTML - go, - glsl, - json, - markdown, - yaml, - sql, - diff, - toml - ] = await Promise.all([ - import("highlight.js/lib/core"), - import("highlight.js/lib/languages/javascript"), - import("highlight.js/lib/languages/typescript"), - import("highlight.js/lib/languages/python"), - import("highlight.js/lib/languages/rust"), - import("highlight.js/lib/languages/c"), - import("highlight.js/lib/languages/cpp"), - import("highlight.js/lib/languages/csharp"), - import("highlight.js/lib/languages/ocaml"), - import("highlight.js/lib/languages/lua"), - import("highlight.js/lib/languages/swift"), - import("highlight.js/lib/languages/bash"), - import("highlight.js/lib/languages/css"), - import("highlight.js/lib/languages/xml"), - import("highlight.js/lib/languages/go"), - import("highlight.js/lib/languages/glsl"), - import("highlight.js/lib/languages/json"), - import("highlight.js/lib/languages/markdown"), - import("highlight.js/lib/languages/yaml"), - import("highlight.js/lib/languages/sql"), - import("highlight.js/lib/languages/diff"), - import("highlight.js/lib/languages/ini"), // handles TOML - import("highlight.js/styles/github-dark.css") - ]); - - const hljs = hljsModule.default; - - hljs.registerLanguage("javascript", javascript.default); - hljs.registerLanguage("typescript", typescript.default); - hljs.registerLanguage("python", python.default); - hljs.registerLanguage("rust", rust.default); - hljs.registerLanguage("c", c.default); - hljs.registerLanguage("cpp", cpp.default); - hljs.registerLanguage("csharp", csharp.default); - hljs.registerLanguage("ocaml", ocaml.default); - hljs.registerLanguage("lua", lua.default); - hljs.registerLanguage("swift", swift.default); - hljs.registerLanguage("bash", bash.default); - hljs.registerLanguage("sh", bash.default); // alias - hljs.registerLanguage("css", css.default); - hljs.registerLanguage("html", xml.default); - hljs.registerLanguage("xml", xml.default); - hljs.registerLanguage("go", go.default); - hljs.registerLanguage("glsl", glsl.default); - hljs.registerLanguage("json", json.default); - hljs.registerLanguage("markdown", markdown.default); - hljs.registerLanguage("yaml", yaml.default); - hljs.registerLanguage("yml", yaml.default); // alias - hljs.registerLanguage("sql", sql.default); - hljs.registerLanguage("diff", diff.default); - hljs.registerLanguage("toml", toml.default); - - hljs.registerLanguage("js", javascript.default); - hljs.registerLanguage("ts", typescript.default); - hljs.registerLanguage("jsx", javascript.default); - hljs.registerLanguage("tsx", typescript.default); - + const hljs = (await import("~/lib/highlight-bundle")).default; return hljs; } diff --git a/src/components/blog/TextEditor.tsx b/src/components/blog/TextEditor.tsx index 243f7c2..f18b29c 100644 --- a/src/components/blog/TextEditor.tsx +++ b/src/components/blog/TextEditor.tsx @@ -24,7 +24,7 @@ import Details from "@tiptap/extension-details"; import DetailsSummary from "@tiptap/extension-details-summary"; import DetailsContent from "@tiptap/extension-details-content"; import { Node } from "@tiptap/core"; -import { createLowlight, common } from "lowlight"; +import { createConfiguredLowlight } from "~/lib/lowlight-bundle"; import { Mermaid } from "./extensions/Mermaid"; import { ConditionalBlock } from "./extensions/ConditionalBlock"; import { ConditionalInline } from "./extensions/ConditionalInline"; @@ -32,69 +32,9 @@ import TextAlign from "@tiptap/extension-text-align"; import Superscript from "@tiptap/extension-superscript"; import Subscript from "@tiptap/extension-subscript"; 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"; -import ocaml from "highlight.js/lib/languages/ocaml"; -import rust from "highlight.js/lib/languages/rust"; -import python from "highlight.js/lib/languages/python"; -import java from "highlight.js/lib/languages/java"; -import go from "highlight.js/lib/languages/go"; -import c from "highlight.js/lib/languages/c"; -import cpp from "highlight.js/lib/languages/cpp"; -import csharp from "highlight.js/lib/languages/csharp"; -import sql from "highlight.js/lib/languages/sql"; -import bash from "highlight.js/lib/languages/bash"; -import json from "highlight.js/lib/languages/json"; -import yaml from "highlight.js/lib/languages/yaml"; -import markdown from "highlight.js/lib/languages/markdown"; -import xml from "highlight.js/lib/languages/xml"; -import php from "highlight.js/lib/languages/php"; -import ruby from "highlight.js/lib/languages/ruby"; -import swift from "highlight.js/lib/languages/swift"; -import kotlin from "highlight.js/lib/languages/kotlin"; -import dockerfile from "highlight.js/lib/languages/dockerfile"; import { BREAKPOINTS, MOBILE_CONFIG, TEXT_EDITOR_CONFIG } from "~/config"; -const lowlight = createLowlight(common); - -lowlight.register("css", css); -lowlight.register("js", js); -lowlight.register("javascript", js); -lowlight.register("ts", ts); -lowlight.register("typescript", ts); -lowlight.register("ocaml", ocaml); -lowlight.register("rust", rust); - -lowlight.register("python", python); -lowlight.register("py", python); -lowlight.register("java", java); -lowlight.register("go", go); -lowlight.register("golang", go); -lowlight.register("c", c); -lowlight.register("cpp", cpp); -lowlight.register("c++", cpp); -lowlight.register("csharp", csharp); -lowlight.register("cs", csharp); -lowlight.register("sql", sql); -lowlight.register("bash", bash); -lowlight.register("shell", bash); -lowlight.register("sh", bash); -lowlight.register("json", json); -lowlight.register("yaml", yaml); -lowlight.register("yml", yaml); -lowlight.register("markdown", markdown); -lowlight.register("md", markdown); -lowlight.register("xml", xml); -lowlight.register("html", xml); -lowlight.register("php", php); -lowlight.register("ruby", ruby); -lowlight.register("rb", ruby); -lowlight.register("swift", swift); -lowlight.register("kotlin", kotlin); -lowlight.register("kt", kotlin); -lowlight.register("dockerfile", dockerfile); -lowlight.register("docker", dockerfile); +const lowlight = createConfiguredLowlight(); const AVAILABLE_LANGUAGES = [ { value: null, label: "Plain Text" }, diff --git a/src/lib/highlight-bundle.ts b/src/lib/highlight-bundle.ts new file mode 100644 index 0000000..d12b09b --- /dev/null +++ b/src/lib/highlight-bundle.ts @@ -0,0 +1,72 @@ +import hljs from "highlight.js/lib/core"; +import javascript from "highlight.js/lib/languages/javascript"; +import typescript from "highlight.js/lib/languages/typescript"; +import python from "highlight.js/lib/languages/python"; +import rust from "highlight.js/lib/languages/rust"; +import c from "highlight.js/lib/languages/c"; +import cpp from "highlight.js/lib/languages/cpp"; +import csharp from "highlight.js/lib/languages/csharp"; +import ocaml from "highlight.js/lib/languages/ocaml"; +import lua from "highlight.js/lib/languages/lua"; +import swift from "highlight.js/lib/languages/swift"; +import bash from "highlight.js/lib/languages/bash"; +import css from "highlight.js/lib/languages/css"; +import xml from "highlight.js/lib/languages/xml"; +import go from "highlight.js/lib/languages/go"; +import glsl from "highlight.js/lib/languages/glsl"; +import json from "highlight.js/lib/languages/json"; +import markdown from "highlight.js/lib/languages/markdown"; +import yaml from "highlight.js/lib/languages/yaml"; +import sql from "highlight.js/lib/languages/sql"; +import diff from "highlight.js/lib/languages/diff"; +import ini from "highlight.js/lib/languages/ini"; +import java from "highlight.js/lib/languages/java"; +import php from "highlight.js/lib/languages/php"; +import ruby from "highlight.js/lib/languages/ruby"; +import kotlin from "highlight.js/lib/languages/kotlin"; +import dockerfile from "highlight.js/lib/languages/dockerfile"; +import "highlight.js/styles/github-dark.css"; + +hljs.registerLanguage("javascript", javascript); +hljs.registerLanguage("js", javascript); +hljs.registerLanguage("typescript", typescript); +hljs.registerLanguage("ts", typescript); +hljs.registerLanguage("python", python); +hljs.registerLanguage("py", python); +hljs.registerLanguage("rust", rust); +hljs.registerLanguage("c", c); +hljs.registerLanguage("cpp", cpp); +hljs.registerLanguage("c++", cpp); +hljs.registerLanguage("csharp", csharp); +hljs.registerLanguage("cs", csharp); +hljs.registerLanguage("ocaml", ocaml); +hljs.registerLanguage("lua", lua); +hljs.registerLanguage("swift", swift); +hljs.registerLanguage("bash", bash); +hljs.registerLanguage("sh", bash); +hljs.registerLanguage("shell", bash); +hljs.registerLanguage("css", css); +hljs.registerLanguage("html", xml); +hljs.registerLanguage("xml", xml); +hljs.registerLanguage("go", go); +hljs.registerLanguage("golang", go); +hljs.registerLanguage("glsl", glsl); +hljs.registerLanguage("json", json); +hljs.registerLanguage("markdown", markdown); +hljs.registerLanguage("md", markdown); +hljs.registerLanguage("yaml", yaml); +hljs.registerLanguage("yml", yaml); +hljs.registerLanguage("sql", sql); +hljs.registerLanguage("diff", diff); +hljs.registerLanguage("toml", ini); +hljs.registerLanguage("ini", ini); +hljs.registerLanguage("java", java); +hljs.registerLanguage("php", php); +hljs.registerLanguage("ruby", ruby); +hljs.registerLanguage("rb", ruby); +hljs.registerLanguage("kotlin", kotlin); +hljs.registerLanguage("kt", kotlin); +hljs.registerLanguage("dockerfile", dockerfile); +hljs.registerLanguage("docker", dockerfile); + +export default hljs; diff --git a/src/lib/lowlight-bundle.ts b/src/lib/lowlight-bundle.ts new file mode 100644 index 0000000..ad6caa7 --- /dev/null +++ b/src/lib/lowlight-bundle.ts @@ -0,0 +1,66 @@ +import { createLowlight } from "lowlight"; +import css from "highlight.js/lib/languages/css"; +import js from "highlight.js/lib/languages/javascript"; +import ts from "highlight.js/lib/languages/typescript"; +import ocaml from "highlight.js/lib/languages/ocaml"; +import rust from "highlight.js/lib/languages/rust"; +import python from "highlight.js/lib/languages/python"; +import java from "highlight.js/lib/languages/java"; +import go from "highlight.js/lib/languages/go"; +import c from "highlight.js/lib/languages/c"; +import cpp from "highlight.js/lib/languages/cpp"; +import csharp from "highlight.js/lib/languages/csharp"; +import sql from "highlight.js/lib/languages/sql"; +import bash from "highlight.js/lib/languages/bash"; +import json from "highlight.js/lib/languages/json"; +import yaml from "highlight.js/lib/languages/yaml"; +import markdown from "highlight.js/lib/languages/markdown"; +import xml from "highlight.js/lib/languages/xml"; +import php from "highlight.js/lib/languages/php"; +import ruby from "highlight.js/lib/languages/ruby"; +import swift from "highlight.js/lib/languages/swift"; +import kotlin from "highlight.js/lib/languages/kotlin"; +import dockerfile from "highlight.js/lib/languages/dockerfile"; + +export function createConfiguredLowlight() { + const lowlight = createLowlight(); + + lowlight.register("css", css); + lowlight.register("js", js); + lowlight.register("javascript", js); + lowlight.register("ts", ts); + lowlight.register("typescript", ts); + lowlight.register("ocaml", ocaml); + lowlight.register("rust", rust); + lowlight.register("python", python); + lowlight.register("py", python); + lowlight.register("java", java); + lowlight.register("go", go); + lowlight.register("golang", go); + lowlight.register("c", c); + lowlight.register("cpp", cpp); + lowlight.register("c++", cpp); + lowlight.register("csharp", csharp); + lowlight.register("cs", csharp); + lowlight.register("sql", sql); + lowlight.register("bash", bash); + lowlight.register("shell", bash); + lowlight.register("sh", bash); + lowlight.register("json", json); + lowlight.register("yaml", yaml); + lowlight.register("yml", yaml); + lowlight.register("markdown", markdown); + lowlight.register("md", markdown); + lowlight.register("xml", xml); + lowlight.register("html", xml); + lowlight.register("php", php); + lowlight.register("ruby", ruby); + lowlight.register("rb", ruby); + lowlight.register("swift", swift); + lowlight.register("kotlin", kotlin); + lowlight.register("kt", kotlin); + lowlight.register("dockerfile", dockerfile); + lowlight.register("docker", dockerfile); + + return lowlight; +} diff --git a/test-prod-server.mjs b/test-prod-server.mjs new file mode 100644 index 0000000..7e448c1 --- /dev/null +++ b/test-prod-server.mjs @@ -0,0 +1,62 @@ +import { createServer } from "http"; +import { readFile } from "fs/promises"; +import { join, extname } from "path"; +import { fileURLToPath } from "url"; +import { dirname } from "path"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); + +const CLIENT_BUILD = join(__dirname, ".vinxi/build/client/_build"); +const PORT = 3001; + +const mimeTypes = { + ".js": "application/javascript", + ".css": "text/css", + ".html": "text/html", + ".json": "application/json", + ".png": "image/png", + ".jpg": "image/jpeg", + ".svg": "image/svg+xml" +}; + +const server = createServer(async (req, res) => { + try { + let filePath = req.url === "/" ? "/index.html" : req.url; + + // Remove query strings + filePath = filePath.split("?")[0]; + + // Serve from assets if it's an asset request + if ( + filePath.startsWith("/assets/") || + filePath.startsWith("/_build/assets/") + ) { + filePath = filePath.replace(/^\/?_build/, ""); + } + + const fullPath = join(CLIENT_BUILD, filePath); + const ext = extname(fullPath); + const contentType = mimeTypes[ext] || "application/octet-stream"; + + const content = await readFile(fullPath); + res.writeHead(200, { "Content-Type": contentType }); + res.end(content); + } catch (err) { + // Try serving index.html for SPA routing + try { + const indexPath = join(CLIENT_BUILD, "index.html"); + const content = await readFile(indexPath); + res.writeHead(200, { "Content-Type": "text/html" }); + res.end(content); + } catch { + res.writeHead(404); + res.end("Not found"); + } + } +}); + +server.listen(PORT, () => { + console.log(`Production test server running at http://localhost:${PORT}`); + console.log(`Serving files from: ${CLIENT_BUILD}`); +});