openvibers/openvibe.games Commits
Games: physgun texture as a 320 KB JPEG (was a 1.43 MB PNG), .obj served as text, only hashed /assets/ immutable (#67)
Changes
nnew file mode 100644BBinary files /dev/null and b/apps/client/public/assets/physgun_tex.jpg differddeleted file mode 100755BBinary files a/apps/client/public/assets/physgun_tex.png and /dev/null differ@@@ -187,7 +187,7 @@ export class Viewmodel {try {const result = await SceneLoader.ImportMeshAsync('', '/assets/', 'physgun.obj', this.scene)const mat = new StandardMaterial('physgun-vm', this.scene)-- mat.diffuseTexture = new Texture('/assets/physgun_tex.png', this.scene)++ mat.diffuseTexture = new Texture('/assets/physgun_tex.jpg', this.scene)mat.specularColor = new Color3(0.15, 0.15, 0.15)mat.emissiveColor = new Color3(0.25, 0.28, 0.32)mat.backFaceCulling = false@@@ -139,7 +139,11 @@ describe('real routes on the apex', () => {expect(asset.headers['content-type']).toBe('text/javascript')expect(asset.headers['cache-control']).toBe('public, max-age=31536000, immutable')expect((await send('/frame.js')).status).toBe(200)-- expect((await send('/assets/tex/wood_planks.jpg')).status).toBe(200)++ const tex = await send('/assets/tex/wood_planks.jpg')++ expect(tex.status).toBe(200)++ expect(tex.headers['cache-control']).toBe(++ 'public, max-age=86400, stale-while-revalidate=604800',++ )})it('answers health, readiness, metrics and the API', async () => {@@@ -74,8 +74,14 @@ const MIME: Record<string, string> = {'.svg': 'image/svg+xml','.ico': 'image/x-icon','.map': 'application/json',++ // Wavefront models are text: a text type lets the CDN compress them (the physgun's 472 KB went out raw as++ // application/octet-stream).++ '.obj': 'text/plain; charset=utf-8',}++/** A file name Vite content-hashed (`main-CE0R2rej.js`): its bytes can never change under that name. */++const HASHED_BUILD_FILE = /-[A-Za-z0-9_-]{8}\.[a-z0-9]+$/++/*** Authorization for the editor HTTP routes. Owner rule (ADR-0007 deleted* the shared secret): a Network staff session with `staff.games.manage` is@@@ -811,13 +817,17 @@ export function createHttpServer(res.writeHead(200, {'content-type': type,// HTML must always revalidate (a stale page pins an old protocol-- // version and can't join). Vite content-hashes /assets/, so those-- // are immutable; everything else gets a modest TTL.++ // version and can't join). Vite content-hashes what it builds into++ // /assets/, so those are immutable. The files public/assets/ copies++ // there keep their names (textures, the physgun model), so they get a++ // day: one of them changed in place would otherwise stay stale a year.'cache-control': filePath.endsWith('.html')? 'no-cache'-- : filePath.includes('/assets/')++ : filePath.includes('/assets/') && HASHED_BUILD_FILE.test(filePath)? 'public, max-age=31536000, immutable'-- : 'public, max-age=3600',++ : filePath.includes('/assets/')++ ? 'public, max-age=86400, stale-while-revalidate=604800'++ : 'public, max-age=3600',})createReadStream(filePath).on('error', (err) => {
new file mode 100644
new file mode 100644
Binary files /dev/null and b/apps/client/public/assets/physgun_tex.jpg differ
Binary files /dev/null and b/apps/client/public/assets/physgun_tex.jpg differ
deleted file mode 100755
deleted file mode 100755
Binary files a/apps/client/public/assets/physgun_tex.png and /dev/null differ
Binary files a/apps/client/public/assets/physgun_tex.png and /dev/null differ
@@ -187,7 +187,7 @@ export class Viewmodel {
@@ -187,7 +187,7 @@ export class Viewmodel {
try {
try {
const result = await SceneLoader.ImportMeshAsync('', '/assets/', 'physgun.obj', this.scene)
const result = await SceneLoader.ImportMeshAsync('', '/assets/', 'physgun.obj', this.scene)
const mat = new StandardMaterial('physgun-vm', this.scene)
const mat = new StandardMaterial('physgun-vm', this.scene)
- mat.diffuseTexture = new Texture('/assets/physgun_tex.png', this.scene)
+ mat.diffuseTexture = new Texture('/assets/physgun_tex.jpg', this.scene)
mat.specularColor = new Color3(0.15, 0.15, 0.15)
mat.specularColor = new Color3(0.15, 0.15, 0.15)
mat.emissiveColor = new Color3(0.25, 0.28, 0.32)
mat.emissiveColor = new Color3(0.25, 0.28, 0.32)
mat.backFaceCulling = false
mat.backFaceCulling = false
@@ -139,7 +139,11 @@ describe('real routes on the apex', () => {
@@ -139,7 +139,11 @@ describe('real routes on the apex', () => {
expect(asset.headers['content-type']).toBe('text/javascript')
expect(asset.headers['content-type']).toBe('text/javascript')
expect(asset.headers['cache-control']).toBe('public, max-age=31536000, immutable')
expect(asset.headers['cache-control']).toBe('public, max-age=31536000, immutable')
expect((await send('/frame.js')).status).toBe(200)
expect((await send('/frame.js')).status).toBe(200)
- expect((await send('/assets/tex/wood_planks.jpg')).status).toBe(200)
+ const tex = await send('/assets/tex/wood_planks.jpg')
+ expect(tex.status).toBe(200)
+ expect(tex.headers['cache-control']).toBe(
+ 'public, max-age=86400, stale-while-revalidate=604800',
+ )
})
})
it('answers health, readiness, metrics and the API', async () => {
it('answers health, readiness, metrics and the API', async () => {
@@ -74,8 +74,14 @@ const MIME: Record<string, string> = {
@@ -74,8 +74,14 @@ const MIME: Record<string, string> = {
'.svg': 'image/svg+xml',
'.svg': 'image/svg+xml',
'.ico': 'image/x-icon',
'.ico': 'image/x-icon',
'.map': 'application/json',
'.map': 'application/json',
+ // Wavefront models are text: a text type lets the CDN compress them (the physgun's 472 KB went out raw as
+ // application/octet-stream).
+ '.obj': 'text/plain; charset=utf-8',
}
}
+/** A file name Vite content-hashed (`main-CE0R2rej.js`): its bytes can never change under that name. */
+const HASHED_BUILD_FILE = /-[A-Za-z0-9_-]{8}\.[a-z0-9]+$/
+
/**
/**
* Authorization for the editor HTTP routes. Owner rule (ADR-0007 deleted
* Authorization for the editor HTTP routes. Owner rule (ADR-0007 deleted
* the shared secret): a Network staff session with `staff.games.manage` is
* the shared secret): a Network staff session with `staff.games.manage` is
@@ -811,13 +817,17 @@ export function createHttpServer(
@@ -811,13 +817,17 @@ export function createHttpServer(
res.writeHead(200, {
res.writeHead(200, {
'content-type': type,
'content-type': type,
// HTML must always revalidate (a stale page pins an old protocol
// HTML must always revalidate (a stale page pins an old protocol
- // version and can't join). Vite content-hashes /assets/, so those
- // are immutable; everything else gets a modest TTL.
+ // version and can't join). Vite content-hashes what it builds into
+ // /assets/, so those are immutable. The files public/assets/ copies
+ // there keep their names (textures, the physgun model), so they get a
+ // day: one of them changed in place would otherwise stay stale a year.
'cache-control': filePath.endsWith('.html')
'cache-control': filePath.endsWith('.html')
? 'no-cache'
? 'no-cache'
- : filePath.includes('/assets/')
+ : filePath.includes('/assets/') && HASHED_BUILD_FILE.test(filePath)
? 'public, max-age=31536000, immutable'
? 'public, max-age=31536000, immutable'
- : 'public, max-age=3600',
+ : filePath.includes('/assets/')
+ ? 'public, max-age=86400, stale-while-revalidate=604800'
+ : 'public, max-age=3600',
})
})
createReadStream(filePath)
createReadStream(filePath)
.on('error', (err) => {
.on('error', (err) => {