## Summary - lazy-load the markdown and diff render paths so they stop inflating initial UI startup work - move shared text rendering helpers out of the markdown path and keep diff rendering on the deferred path - defer the Monaco secondary viewers so the markdown and diff path no longer keeps that work in the main bundle ## Follow-ups - related fork follow-up: Pagecran/CodeNomad#1 - that follow-up is now independent on dev and only keeps the remaining right panel, picker, and tool-call secondary chunking work ## Testing - npm run typecheck --workspace @codenomad/ui - npm run build --workspace @codenomad/ui
168 lines
5.3 KiB
TypeScript
168 lines
5.3 KiB
TypeScript
import fs from "fs"
|
|
import { defineConfig } from "vite"
|
|
import solid from "vite-plugin-solid"
|
|
import { VitePWA } from "vite-plugin-pwa"
|
|
import { resolve } from "path"
|
|
import { copyMonacoPublicAssets } from "./scripts/monaco-public-assets.js"
|
|
|
|
const uiPackageJson = JSON.parse(fs.readFileSync(resolve(__dirname, "package.json"), "utf-8")) as { version?: string }
|
|
const uiVersion = uiPackageJson.version ?? "0.0.0"
|
|
|
|
export default defineConfig({
|
|
root: "./src/renderer",
|
|
plugins: [
|
|
solid(),
|
|
{
|
|
name: "prepare-monaco-public-assets",
|
|
// Ensure Monaco's AMD assets exist in `root/public` for both dev server and builds.
|
|
// These files are gitignored and generated on demand.
|
|
configureServer(server) {
|
|
copyMonacoPublicAssets({
|
|
uiRendererRoot: resolve(__dirname, "src/renderer"),
|
|
warn: (msg) => server.config.logger.warn(msg),
|
|
sourceRoots: [
|
|
resolve(__dirname, "../../node_modules/monaco-editor/min/vs"),
|
|
resolve(__dirname, "node_modules/monaco-editor/min/vs"),
|
|
],
|
|
})
|
|
},
|
|
buildStart() {
|
|
copyMonacoPublicAssets({
|
|
uiRendererRoot: resolve(__dirname, "src/renderer"),
|
|
warn: (msg) => this.warn(msg),
|
|
sourceRoots: [
|
|
resolve(__dirname, "../../node_modules/monaco-editor/min/vs"),
|
|
resolve(__dirname, "node_modules/monaco-editor/min/vs"),
|
|
],
|
|
})
|
|
},
|
|
},
|
|
{
|
|
name: "emit-ui-version",
|
|
generateBundle() {
|
|
this.emitFile({
|
|
type: "asset",
|
|
fileName: "ui-version.json",
|
|
source: JSON.stringify({ uiVersion }, null, 2),
|
|
})
|
|
},
|
|
},
|
|
{
|
|
name: "prepare-pwa-source-icon",
|
|
apply: "build",
|
|
buildStart() {
|
|
// vite-pwa-assets requires the source image inside root/public/
|
|
const source = resolve(__dirname, "src/images/CodeNomad-Icon.png")
|
|
const publicDir = resolve(__dirname, "src/renderer/public")
|
|
const dest = resolve(publicDir, "logo.png")
|
|
fs.mkdirSync(publicDir, { recursive: true })
|
|
fs.copyFileSync(source, dest)
|
|
},
|
|
},
|
|
VitePWA({
|
|
registerType: "autoUpdate",
|
|
injectRegister: "auto",
|
|
pwaAssets: {
|
|
preset: "minimal-2023",
|
|
image: "public/logo.png",
|
|
},
|
|
manifest: {
|
|
name: "CodeNomad",
|
|
short_name: "CodeNomad",
|
|
id: "/",
|
|
start_url: "/",
|
|
display: "standalone",
|
|
display_override: ["window-controls-overlay", "standalone"],
|
|
background_color: "#1a1a1a",
|
|
theme_color: "#1a1a1a",
|
|
},
|
|
workbox: {
|
|
// Workbox defaults to 2 MiB; our main bundle can slightly exceed that.
|
|
// This is a build-time limit for the precache manifest, not a hard runtime cap.
|
|
maximumFileSizeToCacheInBytes: 3 * 1024 * 1024,
|
|
// Preserve server-side auth redirects (e.g., /login) instead of serving cached index.html.
|
|
navigateFallback: null,
|
|
// Only precache static assets (avoid caching HTML documents / routes).
|
|
globPatterns: ["**/*.{js,css,png,jpg,jpeg,svg,webp,ico,woff,woff2,ttf,eot,json,webmanifest}"],
|
|
// Monaco assets can be large; cache them at runtime instead.
|
|
globIgnores: [
|
|
"**/*.html",
|
|
"**/assets/*worker-*.js",
|
|
"**/assets/editor.api-*.js",
|
|
"**/monaco/vs/**/*",
|
|
],
|
|
// Only cache static UI assets; never cache API traffic.
|
|
runtimeCaching: [
|
|
{
|
|
urlPattern: ({ url, request }) => {
|
|
if (url.pathname.startsWith("/api/")) return false
|
|
if (request.destination === "document") return false
|
|
return ["script", "style", "image", "font"].includes(request.destination)
|
|
},
|
|
handler: "CacheFirst",
|
|
options: {
|
|
cacheName: "asset-cache",
|
|
expiration: { maxEntries: 200, maxAgeSeconds: 60 * 60 * 24 * 30 },
|
|
cacheableResponse: { statuses: [0, 200] },
|
|
},
|
|
},
|
|
],
|
|
},
|
|
}),
|
|
],
|
|
css: {
|
|
postcss: "./postcss.config.js",
|
|
},
|
|
resolve: {
|
|
alias: {
|
|
"@": resolve(__dirname, "./src"),
|
|
},
|
|
},
|
|
optimizeDeps: {
|
|
exclude: ["lucide-solid"],
|
|
},
|
|
ssr: {
|
|
noExternal: ["lucide-solid"],
|
|
},
|
|
server: {
|
|
port: 3000,
|
|
},
|
|
build: {
|
|
outDir: "dist",
|
|
rollupOptions: {
|
|
input: {
|
|
main: resolve(__dirname, "./src/renderer/index.html"),
|
|
loading: resolve(__dirname, "./src/renderer/loading.html"),
|
|
},
|
|
output: {
|
|
manualChunks(id) {
|
|
const normalizedId = id.replace(/\\/g, "/")
|
|
|
|
if (normalizedId.includes("/node_modules/@git-diff-view/")) {
|
|
return "git-diff-vendor"
|
|
}
|
|
|
|
if (normalizedId.includes("/node_modules/highlight.js/") || normalizedId.includes("/node_modules/lowlight/")) {
|
|
return "highlight-vendor"
|
|
}
|
|
|
|
if (normalizedId.includes("/node_modules/fast-diff/")) {
|
|
return "fast-diff-vendor"
|
|
}
|
|
|
|
if (normalizedId.includes("/node_modules/monaco-editor/")) {
|
|
return "monaco-vendor"
|
|
}
|
|
|
|
if (
|
|
normalizedId.includes("/src/components/file-viewer/") ||
|
|
normalizedId.includes("/src/lib/monaco/")
|
|
) {
|
|
return "monaco-viewer"
|
|
}
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|