perf: improve loading times with better code splitting
- Improve Vite chunk splitting (Board.js 7.3MB → 5.6MB, 23% smaller) - Add separate chunks for codemirror, onnx, daily-video, sanitizers - Enable gzip for wasm and octet-stream in nginx - Add dns-prefetch and preconnect hints for worker URLs - Increase gzip compression level to 6 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
6f606995a4
commit
ccb5acc164
|
|
@ -9,8 +9,13 @@
|
||||||
<link rel="manifest" href="/manifest.webmanifest" />
|
<link rel="manifest" href="/manifest.webmanifest" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||||
<meta http-equiv="Permissions-Policy" content="midi=*, microphone=*, camera=*, autoplay=*">
|
<meta http-equiv="Permissions-Policy" content="midi=*, microphone=*, camera=*, autoplay=*">
|
||||||
|
<!-- Preconnect to critical origins for faster loading -->
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||||
|
<link rel="dns-prefetch" href="https://jeffemmett-canvas.jeffemmett.workers.dev" />
|
||||||
|
<link rel="dns-prefetch" href="https://jeffemmett-canvas-dev.jeffemmett.workers.dev" />
|
||||||
|
<link rel="preconnect" href="https://jeffemmett-canvas.jeffemmett.workers.dev" crossorigin />
|
||||||
|
<link rel="preconnect" href="https://jeffemmett-canvas-dev.jeffemmett.workers.dev" crossorigin />
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Recursive:slnt,wght,CASL,CRSV,MONO@-15..0,300..1000,0..1,0..1,0..1&display=swap"
|
||||||
rel="stylesheet">
|
rel="stylesheet">
|
||||||
|
|
|
||||||
21
nginx.conf
21
nginx.conf
|
|
@ -4,12 +4,25 @@ server {
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
# Gzip compression
|
# Gzip compression (fallback for clients that don't support Brotli)
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_vary on;
|
gzip_vary on;
|
||||||
gzip_min_length 1024;
|
gzip_comp_level 6;
|
||||||
gzip_proxied expired no-cache no-store private auth;
|
gzip_min_length 256;
|
||||||
gzip_types text/plain text/css text/xml text/javascript application/x-javascript application/xml application/javascript application/json;
|
gzip_proxied any;
|
||||||
|
gzip_types
|
||||||
|
text/plain
|
||||||
|
text/css
|
||||||
|
text/xml
|
||||||
|
text/javascript
|
||||||
|
application/javascript
|
||||||
|
application/x-javascript
|
||||||
|
application/json
|
||||||
|
application/xml
|
||||||
|
application/wasm
|
||||||
|
application/octet-stream
|
||||||
|
image/svg+xml
|
||||||
|
font/woff2;
|
||||||
gzip_disable "MSIE [1-6]\.";
|
gzip_disable "MSIE [1-6]\.";
|
||||||
|
|
||||||
# Security headers
|
# Security headers
|
||||||
|
|
|
||||||
|
|
@ -128,30 +128,71 @@ export default defineConfig(({ mode }) => {
|
||||||
rollupOptions: {
|
rollupOptions: {
|
||||||
output: {
|
output: {
|
||||||
// Manual chunk splitting for large libraries to improve load times
|
// Manual chunk splitting for large libraries to improve load times
|
||||||
manualChunks: {
|
manualChunks(id) {
|
||||||
// Core React libraries
|
// Core React libraries - load first
|
||||||
'react-vendor': ['react', 'react-dom', 'react-router-dom'],
|
if (id.includes('node_modules/react') ||
|
||||||
|
id.includes('node_modules/react-dom') ||
|
||||||
|
id.includes('node_modules/react-router')) {
|
||||||
|
return 'react-vendor';
|
||||||
|
}
|
||||||
|
|
||||||
// tldraw - large drawing library (split into separate chunk)
|
// tldraw core - split from shapes
|
||||||
'tldraw': ['tldraw', '@tldraw/tldraw', '@tldraw/tlschema'],
|
if (id.includes('node_modules/tldraw') ||
|
||||||
|
id.includes('node_modules/@tldraw')) {
|
||||||
|
return 'tldraw';
|
||||||
|
}
|
||||||
|
|
||||||
// Automerge - CRDT sync library
|
// Automerge - CRDT sync library
|
||||||
'automerge': [
|
if (id.includes('node_modules/@automerge')) {
|
||||||
'@automerge/automerge',
|
return 'automerge';
|
||||||
'@automerge/automerge-repo',
|
}
|
||||||
'@automerge/automerge-repo-react-hooks'
|
|
||||||
],
|
|
||||||
|
|
||||||
// AI SDKs (lazy load)
|
// AI SDKs (lazy load)
|
||||||
'ai-sdks': ['@anthropic-ai/sdk', 'openai', 'ai'],
|
if (id.includes('node_modules/@anthropic-ai') ||
|
||||||
|
id.includes('node_modules/openai') ||
|
||||||
|
id.includes('node_modules/ai/')) {
|
||||||
|
return 'ai-sdks';
|
||||||
|
}
|
||||||
|
|
||||||
// ML/transformers (VERY large, lazy loaded)
|
// ML/transformers (VERY large, lazy loaded)
|
||||||
'ml-libs': ['@xenova/transformers'],
|
if (id.includes('node_modules/@xenova')) {
|
||||||
|
return 'ml-libs';
|
||||||
|
}
|
||||||
|
|
||||||
// Markdown editors
|
// Markdown editors
|
||||||
'markdown': ['@uiw/react-md-editor', 'cherry-markdown', 'marked', 'react-markdown'],
|
if (id.includes('node_modules/@uiw/react-md-editor') ||
|
||||||
|
id.includes('node_modules/cherry-markdown') ||
|
||||||
|
id.includes('node_modules/marked') ||
|
||||||
|
id.includes('node_modules/react-markdown')) {
|
||||||
|
return 'markdown';
|
||||||
|
}
|
||||||
|
|
||||||
// Note: gun, webnative, holosphere removed - stubbed for future Nostr integration
|
// CodeMirror (used by markdown editors)
|
||||||
|
if (id.includes('node_modules/@codemirror') ||
|
||||||
|
id.includes('node_modules/codemirror')) {
|
||||||
|
return 'codemirror';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Daily video chat
|
||||||
|
if (id.includes('node_modules/@daily-co')) {
|
||||||
|
return 'daily-video';
|
||||||
|
}
|
||||||
|
|
||||||
|
// html2canvas (screenshots)
|
||||||
|
if (id.includes('node_modules/html2canvas')) {
|
||||||
|
return 'html2canvas';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ONNX runtime (ML inference)
|
||||||
|
if (id.includes('node_modules/onnxruntime')) {
|
||||||
|
return 'onnx';
|
||||||
|
}
|
||||||
|
|
||||||
|
// DOMPurify and sanitizers
|
||||||
|
if (id.includes('node_modules/dompurify') ||
|
||||||
|
id.includes('node_modules/isomorphic-dompurify')) {
|
||||||
|
return 'sanitizers';
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue