Skip to content

Commit 0df8ff0

Browse files
authored
Move theme-init.js to assets/ (#3176)
Closes #3175 `theme-init.js` was in `public/` at the root, so it ended up at `dist/theme-init.js`. In production, Nexus [serves](https://github.com/oxidecomputer/omicron/blob/b2b1e393a4072f041ee833656fcd57e683704d0e/nexus/src/external_api/console_api.rs#L409-L439) console static files via explicitly defined routes — there's a `/assets/{path:.*}` route but no route for files at the root like `/theme-init.js`. The fix moves `theme-init.js` from `public/` to `public/assets/` so it lands in `dist/assets/` and is served by the existing `/assets/{path:.*}` route. The Vite plugin now references `/assets/theme-init.js?v={hash}`.
1 parent aec681b commit 0df8ff0

3 files changed

Lines changed: 20 additions & 8 deletions

File tree

app/api/__tests__/safety.spec.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,18 @@ it('e2e tests are only in test/e2e or test/visual', () => {
8383
}
8484
})
8585

86+
// In production, Nexus only serves /assets/* and /index.html — files at other
87+
// paths under public/ would work in Vite dev but 404 in production.
88+
// https://github.com/oxidecomputer/omicron/blob/b2b1e39/nexus/src/external_api/console_api.rs#L409-L439
89+
it('public/ only contains assets/', () => {
90+
const entries = fs.readdirSync(path.resolve(__dirname, '../../../public'))
91+
expect(entries).toMatchInlineSnapshot(`
92+
[
93+
"assets",
94+
]
95+
`)
96+
})
97+
8698
// 8-4-4-4-12 hex digits
8799
const UUID_RE = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
88100

vite.config.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -133,21 +133,21 @@ export default defineConfig(({ mode }) => ({
133133
},
134134
{
135135
// Inject theme-init.js as a classic (non-module) render-blocking script
136-
// so it sets data-theme before first paint. It lives in public/ so it
137-
// passes CSP default-src 'self'. We inject it here rather than putting
138-
// it in index.html because Vite tries to bundle any <script src> it finds
139-
// there. Content hash query param handles cache-busting since public/
140-
// files aren't fingerprinted by Vite. We cache static assets for a year,
141-
// so we need the hash.
136+
// so it sets data-theme before first paint. It lives in public/assets/
137+
// so it passes CSP default-src 'self' and is served by the /assets/*
138+
// route in Nexus. We inject it here rather than putting it in index.html
139+
// because Vite tries to bundle any <script src> it finds there. Content
140+
// hash query param handles cache-busting since public/ files aren't
141+
// fingerprinted by Vite.
142142
name: 'theme-init',
143143
transformIndexHtml() {
144-
const content = readFileSync(resolve(__dirname, 'public/theme-init.js'))
144+
const content = readFileSync(resolve(__dirname, 'public/assets/theme-init.js'))
145145
const hash = createHash('sha256').update(content).digest('hex').slice(0, 8)
146146
return [
147147
{
148148
injectTo: 'head-prepend',
149149
tag: 'script',
150-
attrs: { src: `/theme-init.js?v=${hash}` },
150+
attrs: { src: `/assets/theme-init.js?v=${hash}` },
151151
},
152152
]
153153
},

0 commit comments

Comments
 (0)