Repository navigation
Expand file tree
/
Copy pathvite.config.ts
More file actions
138 lines (137 loc) · 5.31 KB
/
Copy pathvite.config.ts
File metadata and controls
138 lines (137 loc) · 5.31 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
import { existsSync } from "node:fs";
import path from "node:path";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import electron from "vite-plugin-electron/simple";
// https://vitejs.dev/config/
export default defineConfig({
// Vite's dependency cache defaults to `node_modules/.vite`, and in this repo every
// worktree's `node_modules` is a JUNCTION to the main checkout's — so the main repo
// and every worktree share ONE cache directory. Running two dev servers at once
// (routine here) then has them re-optimising into each other's cache: the second run
// rewrites `deps/` while the first has already handed the browser URLs stamped with
// the previous `?v=` token, so the renderer ends up holding two generations of the
// same dependency at once — "Invalid hook call / more than one copy of React",
// `useState` null, blank editor. Same symptom as the `dedupe` note below, different
// cause: that one is about resolution, this one about a cache with several writers.
// Keeping the cache beside the checkout that owns it (NOT under `node_modules`, which
// is the junction) makes concurrent servers independent.
cacheDir: path.resolve(__dirname, ".vite-cache"),
plugins: [
react(),
electron({
main: {
entry: "electron/main.ts",
onstart({ startup }) {
if (process.env.NO_ELECTRON) {
console.log("NO_ELECTRON is set, skipping Electron startup.");
return;
}
const env = { ...process.env };
delete env.ELECTRON_RUN_AS_NODE;
/*
* The Studio, which the app hosts in a window.
*
* `npm run app` (scripts/launch.mjs) points at it; `npm run dev` did not,
* so the one command that gives you HMR — the command you want for any
* design work — came up with the Studio window reporting that it could
* not find the Studio. Same resolution order as launch.mjs: an explicit
* RM_STUDIO_BIN wins, otherwise the sibling checkout, otherwise leave it
* unset and let the window say why.
*/
if (!env.RM_STUDIO_BIN) {
const sibling = path.resolve(
__dirname,
"..",
"rolemodel-openscreen",
"bin",
"rm-studio.mjs",
);
if (existsSync(sibling)) env.RM_STUDIO_BIN = sibling;
}
return startup(["."], { env });
},
vite: {
build: {},
},
},
preload: {
// Two preloads, deliberately. `preload.ts` carries the whole
// electronAPI surface for the app's own windows; `studio-preload.ts`
// carries two calls for the Studio window, which loads a page served
// over HTTP by a separate process. Giving that page the full surface
// would hand any page that server ever serves the run of the machine.
input: [
path.join(__dirname, "electron/preload.ts"),
path.join(__dirname, "electron/studio-preload.ts"),
],
vite: {
build: {
rollupOptions: {
// The plugin defaults preloads to one inlined bundle, which
// rollup refuses with more than one input. Neither preload has a
// dynamic import, so there is nothing to inline and nothing lost;
// each just emits its own file.
output: { inlineDynamicImports: false },
},
},
},
},
renderer: process.env.NODE_ENV === "test" ? undefined : {},
}),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "src"),
},
// This checkout is a git worktree nested under the main repo, and its
// node_modules is incomplete (e.g. zustand is absent), so bare deps that
// aren't present here resolve UP into the main repo's node_modules and drag
// in a SECOND copy of React — "Invalid hook call / more than one copy of
// React" → blank editor. Force every importer (app + hoisted deps like
// zustand) onto this checkout's single React copy. Harmless in a normal
// full install (already a single copy there); required to run from a worktree.
dedupe: ["react", "react-dom", "react/jsx-runtime"],
},
server: {
watch: {
// Nested worktrees (`.claude/worktrees/**`) and delegate task checkouts
// (`.cc-delegate/**`) each carry their own full copy of the repo, including
// their own vite/tsconfig files. Without this, deleting/touching one (e.g.
// `git worktree remove`) fires hundreds of change events across the main
// dev server, forcing repeated full-reloads unrelated to any real source
// change — observed as the running app going unresponsive/stale mid-session.
//
// `crates/thirdparty/**` is the vendored ffmpeg tree the Rust compositor
// builds against (see crates/.cargo/config.toml). It is gitignored but still
// watched: several thousand files, including a doc/ directory full of HTML,
// whose extraction fires the same reload storm.
ignored: ["**/.claude/worktrees/**", "**/.cc-delegate/**", "**/crates/thirdparty/**"],
},
},
build: {
target: "esnext",
minify: "terser",
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
pure_funcs: ["console.log", "console.debug"],
},
},
rollupOptions: {
output: {
manualChunks(id) {
if (id.includes("react-dom") || id.includes("/react/")) return "react-vendor";
if (
id.includes("mediabunny") ||
id.includes("mp4box") ||
id.includes("fix-webm-duration")
)
return "video-processing";
},
},
},
chunkSizeWarningLimit: 1000,
},
});