Repository navigation
Expand file tree
/
Copy pathvite.config.ts
More file actions
161 lines (159 loc) · 5.84 KB
/
Copy pathvite.config.ts
File metadata and controls
161 lines (159 loc) · 5.84 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
153
154
155
156
157
158
159
160
161
/// <reference types="vitest/config" />
import fs from 'node:fs';
import path from 'node:path';
import { defineConfig, type Plugin } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
/** Vite copies public/ and dereference symlinks; keep local MCAPs as links. */
function preserveUserMcapSymlinks(): Plugin {
return {
name: 'preserve-user-mcap-symlinks',
closeBundle() {
const src = path.resolve(import.meta.dirname, 'public/user-mcaps');
const dst = path.resolve(import.meta.dirname, 'dist/user-mcaps');
if (!fs.existsSync(src)) {
return;
}
fs.rmSync(dst, { recursive: true, force: true });
fs.mkdirSync(dst, { recursive: true });
for (const name of fs.readdirSync(src)) {
if (!name.endsWith('.mcap')) {
continue;
}
const target = fs.realpathSync(path.join(src, name));
fs.symlinkSync(target, path.join(dst, name));
}
},
};
}
export default defineConfig({
// Relative base so the SPA works both at domain root (rosview.com) and under a path prefix (io-ai.tech/rosview/).
base: './',
test: {
environment: 'node',
include: ['src/**/*.test.ts', 'src/**/*.test.tsx'],
coverage: {
provider: 'v8',
include: ['src/**/*.{ts,tsx}'],
exclude: [
'src/**/*.test.{ts,tsx}',
'src/**/*.worker.ts',
'src/entrypoints/main.tsx',
'src/entrypoints/App.tsx',
],
reporter: ['text', 'lcov'],
thresholds: {
lines: 50,
functions: 50,
},
},
},
// Tailwind v4 ships a dedicated Vite plugin (replaces the v3 PostCSS plugin;
// `postcss.config.js` is gone — v4 handles @import and vendor prefixes itself).
plugins: [react(), tailwindcss(), preserveUserMcapSymlinks()],
resolve: {
alias: {
'@': path.resolve(import.meta.dirname, './src'),
// protobufjs probes require('fs') at load; silent null avoids Vite's noisy external stub.
// Keep `node:fs` unaliased so Vitest/Node fixtures can still use the real module.
fs: path.resolve(import.meta.dirname, './src/shims/empty-fs.js'),
},
},
// Native Vite asset URLs (`*.wasm?url`); no vite-plugin-wasm (ESM wasm import path unused).
assetsInclude: ['**/*.wasm'],
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "credentialless",
},
},
preview: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "credentialless",
},
},
optimizeDeps: {
// Playback workers are imported only after a dataset is opened. Pre-bundle their
// transitive parser/decompression deps up front so first-open in dev does not
// trigger Vite's "new dependencies optimized" reload and bounce back to home.
include: [
'@foxglove/omgidl-parser',
'@foxglove/omgidl-serialization',
'@foxglove/ros2idl-parser',
'@foxglove/rosmsg',
'@foxglove/rosmsg-serialization',
'@foxglove/rosmsg2-serialization',
'@ioai/wasm-zstd',
'@mcap/browser',
'@mcap/core',
'eventemitter3',
'flatbuffers/js/flexbuffers.js',
'intervals-fn',
'lz4js',
'protobufjs',
'protobufjs/ext/descriptor',
'@ioai/hdf5',
],
},
worker: {
format: 'es',
rolldownOptions: {
onLog(level, log, defaultHandler) {
if (level === 'warn' && typeof log !== 'string') {
const paths = [log.id, log.loc?.file, ...(log.ids ?? [])].filter(Boolean) as string[];
const inNodeModules = paths.some((p) => p.includes('/node_modules/'));
const isViteResolveWarn =
log.plugin === 'rolldown:vite-resolve' && log.message.includes('node_modules');
if (inNodeModules || isViteResolveWarn) return;
}
defaultHandler(level, log);
},
output: {
format: 'es',
// @ioai/hdf5 dynamic import must stay in the worker bundle — splitting it
// emits a sibling chunk (dist-*.js) that workers resolve with a broken
// relative URL under preview/assets/.
codeSplitting: false,
},
},
},
build: {
target: 'esnext',
// Modern browsers only (esnext); skip ~1KB modulepreload polyfill.
modulePreload: { polyfill: false },
// Large wasm/worker chunks make gzip size reporting slow (Vite build options).
reportCompressedSize: false,
chunkSizeWarningLimit: 1200,
rolldownOptions: {
checks: {
// The worker-heavy build legitimately spends time in Vite worker/CSS plugins;
// keep chunk-size warnings meaningful without failing on plugin timing noise.
pluginTimings: false,
},
onLog(level, log, defaultHandler) {
if (level === 'warn' && typeof log !== 'string') {
const paths = [log.id, log.loc?.file, ...(log.ids ?? [])].filter(Boolean) as string[];
const inNodeModules = paths.some((p) => p.includes('/node_modules/'));
const isViteResolveWarn =
log.plugin === 'rolldown:vite-resolve' && log.message.includes('node_modules');
if (inNodeModules || isViteResolveWarn) return;
}
defaultHandler(level, log);
},
output: {
// Prefer Rolldown codeSplitting.groups over deprecated manualChunks (Vite 8).
codeSplitting: {
groups: [
{ name: 'vendor-dockview', test: /dockview/, priority: 30 },
{ name: 'vendor-three', test: /(?:^|[\\/])three(?:[\\/]|$)/, priority: 30 },
{ name: 'vendor-uplot', test: /(?:^|[\\/])uplot(?:[\\/]|$)/, priority: 30 },
{ name: 'vendor-mcap', test: /@mcap[\\/]core/, priority: 30 },
{ name: 'vendor-rosbag', test: /@foxglove[\\/]rosbag/, priority: 30 },
{ name: 'vendor-ioai-hdf5', test: /@ioai[\\/]hdf5/, priority: 30 },
],
},
},
},
},
});