Repository navigation
Expand file tree
/
Copy pathvite.config.js
More file actions
86 lines (81 loc) · 2.54 KB
/
Copy pathvite.config.js
File metadata and controls
86 lines (81 loc) · 2.54 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
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { execSync } from 'node:child_process'
import { gzipSync } from 'node:zlib'
// GitHub Pages cannot send response headers, so the policy ships as a <meta>
// tag. It is added to built pages only: the dev server injects inline styles
// for hot reload, which this policy would (correctly) block.
const CSP = [
"default-src 'none'",
"script-src 'self'",
"style-src 'self'",
"img-src 'self' data:",
"font-src 'self'",
"connect-src 'self'",
"manifest-src 'self'",
"base-uri 'none'",
"form-action 'none'",
"object-src 'none'",
'upgrade-insecure-requests',
].join('; ')
const securityMeta = {
name: 'security-meta',
apply: 'build',
transformIndexHtml(html) {
return html.replace(
'<meta charset="UTF-8" />',
`<meta charset="UTF-8" />\n <meta http-equiv="Content-Security-Policy" content="${CSP}" />`,
)
},
}
function sh(cmd) {
try {
return execSync(cmd, { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim()
} catch (e) {
return e.stdout?.toString().trim() ?? ''
}
}
// Facts about this build, measured rather than written by hand, served as
// build-info.json for the "hardened system" panel on the page.
const buildInfo = {
name: 'build-info',
apply: 'build',
generateBundle(_, bundle) {
let js = 0
let css = 0
let fonts = 0
for (const file of Object.values(bundle)) {
const body = file.type === 'chunk' ? file.code : file.source
if (file.fileName.endsWith('.js')) js += gzipSync(body).length
else if (file.fileName.endsWith('.css')) css += gzipSync(body).length
else if (file.fileName.endsWith('.woff2')) fonts += 1
}
let vulnerabilities = null
try {
const audit = JSON.parse(sh('npm audit --omit=dev --json'))
vulnerabilities = audit.metadata?.vulnerabilities?.total ?? null
} catch {
vulnerabilities = null
}
const sha = process.env.GITHUB_SHA || sh('git rev-parse HEAD')
const commit = /^[0-9a-f]{40}$/.test(sha) ? sha : null
const info = {
commit,
builtAt: new Date().toISOString(),
jsGzipBytes: js,
cssGzipBytes: css,
fontFiles: fonts,
csp: CSP,
vulnerabilities,
}
this.emitFile({ type: 'asset', fileName: 'build-info.json', source: JSON.stringify(info, null, 2) })
},
}
export default defineConfig({
plugins: [react(), securityMeta, buildInfo],
build: {
// Keep fonts as files: font-src 'self' does not allow data: URIs.
assetsInlineLimit: 0,
sourcemap: false,
},
})