-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvite.config.ts
More file actions
152 lines (140 loc) · 5.21 KB
/
vite.config.ts
File metadata and controls
152 lines (140 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
import path from 'path';
import { defineConfig, Plugin } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
// Pattern for generated components - used to split Svelte plugin instances
const GENERATED_PATTERN = 'src/generated/**/*.svelte';
const DEFAULT_DEV_SERVER_HOST = '127.0.0.1';
const DEV_SERVER_HOST = process.env.PANTOGRAPH_VITE_HOST || DEFAULT_DEV_SERVER_HOST;
/**
* Vite plugin to handle HMR for generated components.
* Prevents full page reload when files are deleted/created during undo operations.
* Works in conjunction with a separate Svelte plugin instance that has hot: false.
*/
function generatedComponentsHMR(): Plugin {
return {
name: 'generated-components-hmr',
enforce: 'pre', // Run before other plugins including Svelte
hotUpdate({ type, file, server }) {
// Only handle files in src/generated/
if (!file.includes('/src/generated/')) {
return; // Let Vite handle normally
}
// Skip validation temp files - these are created/deleted during component validation
// and should not trigger HMR events
if (file.includes('.validate-') || file.endsWith('.tmp')) {
return; // Ignore temp files
}
const eventMap: Record<string, string> = {
'delete': 'generated-component-deleted',
'create': 'generated-component-created',
'update': 'generated-component-updated'
};
const event = eventMap[type];
if (event) {
// Handle module graph operations
if (type === 'delete') {
server.moduleGraph.onFileDelete(file);
} else if (type === 'update') {
// Invalidate module so next import gets fresh content
const module = server.moduleGraph.getModuleById(file);
if (module) {
server.moduleGraph.invalidateModule(module);
}
}
// Normalize path to URL-style for frontend (Vite provides absolute filesystem paths)
const relativePath = '/src/generated/' + file.split('/src/generated/')[1];
// Send custom event to frontend - we handle HMR ourselves
// Check if WebSocket is available and ready before sending
try {
if (server.ws) {
server.ws.send({
type: 'custom',
event,
data: { file: relativePath }
});
}
} catch (err) {
// Ignore WebSocket errors (connection closed, EPIPE, etc.)
// This can happen during app shutdown or HMR reconnection
console.debug(`[generated-components-hmr] WebSocket send failed (likely shutting down):`, err);
}
console.log(`[generated-components-hmr] ${type}:`, relativePath);
// Return empty array to prevent default HMR and stop propagation to Svelte plugin
return [];
}
return undefined;
}
};
}
export default defineConfig(() => {
return {
server: {
port: 3001,
host: DEV_SERVER_HOST,
strictPort: true,
watch: {
// Ignore Rust build artifacts - target/doc alone is 2.2GB with thousands of files
ignored: ['**/src-tauri/target/**']
}
},
clearScreen: false,
plugins: [
generatedComponentsHMR(), // Must be before svelte() to intercept first
// Normal Svelte with HMR - excludes generated components
svelte({
exclude: GENERATED_PATTERN,
}),
// Generated components - compiled but NO HMR (we handle it ourselves via custom events)
svelte({
include: GENERATED_PATTERN,
hot: false,
configFile: false, // Don't read svelte.config.js twice
experimental: {
// Avoid compiling `.svelte.js` modules twice across the two Svelte plugin instances.
// The primary Svelte instance handles module compilation for dependencies such as @xyflow/svelte.
compileModule: {
exclude: ['**']
}
}
})
],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'$lib': path.resolve(__dirname, 'src/lib'),
'$features': path.resolve(__dirname, 'src/features'),
'$shared': path.resolve(__dirname, 'src/shared'),
}
},
optimizeDeps: {
include: [
// Icon library used by generated components
'lucide-svelte',
// Svelte internals
'svelte',
'svelte/animate',
'svelte/motion',
'svelte/store',
'svelte/transition',
// Other commonly used deps
'@tauri-apps/api/core',
'@tauri-apps/plugin-dialog',
],
},
build: {
// three.module.js is a single large upstream module; keep warnings focused on true regressions.
chunkSizeWarningLimit: 800,
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes('node_modules/three')) return 'three';
if (id.includes('node_modules/@xyflow')) return 'xyflow';
if (id.includes('node_modules/@tauri-apps')) return 'tauri';
if (id.includes('node_modules')) return 'vendor';
return undefined;
},
},
},
},
};
});