Repository navigation
Expand file tree
/
Copy pathvite.config.ts
More file actions
105 lines (99 loc) · 4.1 KB
/
Copy pathvite.config.ts
File metadata and controls
105 lines (99 loc) · 4.1 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
import react from "@vitejs/plugin-react";
import { fileURLToPath } from "node:url";
import path from "path";
import { visualizer } from "rollup-plugin-visualizer";
import AutoImport from "unplugin-auto-import/vite";
import { defineConfig } from "vite";
import RubyPlugin from "vite-plugin-ruby";
import { codeSplittingGroups } from "./config/vite/manual-chunks.ts";
import { staleModuleGuard } from "./config/vite/stale-module-guard.ts";
const rootPath = path.dirname(fileURLToPath(import.meta.url));
function stripCjsExportsPlugin() {
return {
name: "strip-cjs-exports",
transform(code: string, id: string) {
if (id.endsWith("routes.js")) {
return code.replace(/^Object\.defineProperty\(exports.*$/mu, "").replace(/^exports\.\w+\s*=.*$/gmu, "");
}
},
};
}
// Some client-side security software (antivirus web shields, tracker blockers, corporate
// proxies) block or quarantine requests purely on the URL/filename containing tracker-like
// words such as "google_analytics". Our chunk names come from the source module name, so a
// module named google_analytics.ts produced a chunk literally called
// google_analytics-<hash>.js. When a page *statically* imports that chunk, a client-side
// block of that one file stops the whole page from ever mounting, leaving a blank screen.
//
// Renaming the emitted chunk is not cosmetic: it removes the substring these tools pattern
// match on, so the module ships as ordinary application code. This does not disable or hide
// any analytics behaviour, and it does not change what the module does — only the filename
// it is served under. See the "blank product editor" reports (2026-07-26).
const BLOCKABLE_NAME_PATTERNS = [/google_analytics/u, /google-analytics/u, /googletagmanager/u, /gtag/u];
function sanitizeChunkName(name: string) {
return BLOCKABLE_NAME_PATTERNS.some((pattern) => pattern.test(name)) ? "third_party_tracking" : name;
}
export default defineConfig(() => ({
plugins: [
RubyPlugin(),
react(),
staleModuleGuard(),
AutoImport({
imports: [
{ "$app/utils/routes": [["*", "Routes"]] },
{
jquery: [
["default", "$"],
["default", "jQuery"],
],
},
],
}),
stripCjsExportsPlugin(),
// Bundle visualizer, opt-in: it adds about a quarter to a production build.
// Run `BUNDLE_STATS=1 npx vite build` then open tmp/bundle-stats.html to audit chunk sizes.
...(process.env.BUNDLE_STATS === "1"
? [
visualizer({
filename: "tmp/bundle-stats.html",
gzipSize: true,
brotliSize: true,
}),
]
: []),
],
resolve: {
alias: {
$app: path.join(rootPath, "app/javascript"),
$assets: path.join(rootPath, "public"),
$vendor: path.join(rootPath, "vendor/assets/javascripts"),
jwplayer: path.join(rootPath, "vendor/assets/components/jwplayer-7.12.13/jwplayer"),
},
},
define: {
SSR: false,
"process.env.NODE_ENV": JSON.stringify(process.env.NODE_ENV || "test"),
"process.env.RAILS_ENV": JSON.stringify(process.env.RAILS_ENV || "test"),
"process.env.PROTOCOL": JSON.stringify(process.env.PROTOCOL || "https"),
"process.env": "{}",
},
build: {
// Stable content-hash filenames for long-lived CDN caching.
// Rollup's default [hash] is already content-based, but we make the
// pattern explicit so it survives Vite major bumps.
rollupOptions: {
output: {
codeSplitting: { groups: codeSplittingGroups },
// [name]-[hash] keeps filenames readable in devtools / logs.
// sanitizeChunkName strips tracker-like words (see above) so client-side
// blockers can't take a page down by refusing one of its static imports.
chunkFileNames: (chunkInfo) => `assets/${sanitizeChunkName(chunkInfo.name)}-[hash].js`,
entryFileNames: "assets/[name]-[hash].js",
assetFileNames: "assets/[name]-[hash][extname]",
},
},
// Raise chunk size warning limit — the vendor chunk is large but it's a single cacheable unit
// that changes infrequently.
chunkSizeWarningLimit: 800,
},
}));