Repository navigation
Expand file tree
/
Copy pathvite.config.ts
More file actions
65 lines (63 loc) · 2.91 KB
/
Copy pathvite.config.ts
File metadata and controls
65 lines (63 loc) · 2.91 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
/// <reference types="vitest/config" />
import { defineConfig, type Plugin } from 'vitest/config';
import react from '@vitejs/plugin-react';
import { writeFileSync } from 'node:fs';
import path from 'path';
// P2-A7: write the entry chunk's REAL (pre-minification) module ids so assert-first-paint-lean.mjs can gate
// on them — the identifier grep it replaces is blind to esbuild minification. Non-throwing: writes the
// report; the CI script is the gate. Security F3 fix: write to a REPO-ROOT path (NOT dist/, so it is never
// served) and strip the absolute prefix to repo-relative ids (no dev-home-dir disclosure).
function firstPaintLeanGuard(): Plugin {
return {
name: 'first-paint-lean-guard',
writeBundle(_options, bundle) {
const root = process.cwd();
const entry = Object.values(bundle).find((c) => c.type === 'chunk' && c.isEntry);
const moduleIds = (entry && entry.type === 'chunk' ? Object.keys(entry.modules) : []).map((id) =>
id.startsWith(root) ? id.slice(root.length) : id,
);
writeFileSync(path.join(root, '.first-paint-entry-modules.json'), JSON.stringify(moduleIds));
},
};
}
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react(), firstPaintLeanGuard()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
'@utils': path.resolve(__dirname, './src/utils'),
'@config': path.resolve(__dirname, './src/config'),
'@types': path.resolve(__dirname, './src/types'),
'@hooks': path.resolve(__dirname, './src/hooks'),
'@store': path.resolve(__dirname, './src/store'),
},
},
server: {
port: 5173,
},
// (Vitest config lives in vitest.config.ts — it takes precedence over any test block here.)
build: {
outDir: 'dist',
// Keep React in a stable 'vendor' chunk out of the tiny app-shell entry. The engine/registry/tokenizer
// stay lazy via dynamic import()/worker. Charts are hand-rolled SVG (no recharts), so no chart chunk.
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
// recharts (+ its d3/victory/react-smooth deps) into one lazy chunk, out of first-paint (P1-A25).
charts: ['recharts'],
},
},
},
// Do NOT ship source maps to production (security-venue launch): sourcemap:true published .js.map with
// full sourcesContent (the entire annotated original TS source) as immutable-cached, publicly-served
// assets, and let an unqualified claim in a source comment survive in the map after minification stripped
// it from the .js. Off for the shipped build. [0D review]
sourcemap: false,
// D3: never inline an asset (font/glyph) as a data: URI in CSS — font-src 'self' has no data: and
// would silently drop it. Keep every asset a same-origin file the strict CSP admits.
assetsInlineLimit: 0,
},
});