perf: 프로필 프런트엔드 자산을 커밋 단위로 공유한다
정적 운영 빌드에서 프로필별 base와 API 설정을 런타임 JSON으로 분리하고, 공용 Vite 번들과 sourcemap을 한 번만 생성·게시한다. Preview와 기존 정적 artifact의 전환 호환 경계는 유지한다.
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import { describe, it } from 'node:test';
|
||||
|
||||
import { resolveGameFrontendRuntimeConfig } from '../src/config/runtimeConfig.ts';
|
||||
|
||||
const documentWithConfig = (value: string | null): Pick<Document, 'getElementById'> => ({
|
||||
getElementById: () => (value === null ? null : ({ textContent: value } as HTMLElement)),
|
||||
});
|
||||
|
||||
void describe('game frontend runtime config', () => {
|
||||
void it('prefers the embedded profile wrapper config over build-time fallbacks', () => {
|
||||
const config = resolveGameFrontendRuntimeConfig(
|
||||
documentWithConfig(
|
||||
JSON.stringify({
|
||||
version: 1,
|
||||
profile: 'pya',
|
||||
profileName: 'pya:default',
|
||||
appBasePath: '/pya',
|
||||
gameApiUrl: '/pya/api/trpc',
|
||||
gameSseUrl: '/pya/api/events',
|
||||
gatewayApiUrl: '/gateway/api/trpc',
|
||||
gatewayWebUrl: '/gateway/',
|
||||
buildCommitSha: 'a'.repeat(40),
|
||||
assetReleaseId: `${'a'.repeat(40)}-${'b'.repeat(16)}`,
|
||||
})
|
||||
),
|
||||
{
|
||||
VITE_APP_BASE_PATH: '/che',
|
||||
VITE_GAME_API_URL: '/che/api/trpc',
|
||||
VITE_GAME_SSE_URL: '/che/api/events',
|
||||
VITE_GAME_PROFILE: 'che',
|
||||
VITE_BUILD_COMMIT_SHA: 'c'.repeat(40),
|
||||
}
|
||||
);
|
||||
|
||||
assert.equal(config.profile, 'pya');
|
||||
assert.equal(config.appBasePath, '/pya/');
|
||||
assert.equal(config.gameApiUrl, '/pya/api/trpc');
|
||||
assert.equal(config.gameSseUrl, '/pya/api/events');
|
||||
assert.equal(config.buildCommitSha, 'a'.repeat(40));
|
||||
assert.equal(config.assetReleaseId, `${'a'.repeat(40)}-${'b'.repeat(16)}`);
|
||||
});
|
||||
|
||||
void it('keeps preview and local development compatible through Vite environment fallbacks', () => {
|
||||
const config = resolveGameFrontendRuntimeConfig(documentWithConfig(null), {
|
||||
VITE_APP_BASE_PATH: '/hwe',
|
||||
VITE_GAME_API_URL: '/hwe/api/trpc',
|
||||
VITE_GAME_SSE_URL: '/hwe/api/events',
|
||||
VITE_GAME_PROFILE: 'hwe',
|
||||
VITE_GATEWAY_API_URL: '/gateway/api/trpc',
|
||||
VITE_GATEWAY_WEB_URL: '/gateway/',
|
||||
VITE_BUILD_COMMIT_SHA: 'd'.repeat(40),
|
||||
});
|
||||
|
||||
assert.deepEqual(config, {
|
||||
version: 1,
|
||||
profile: 'hwe',
|
||||
appBasePath: '/hwe/',
|
||||
gameApiUrl: '/hwe/api/trpc',
|
||||
gameSseUrl: '/hwe/api/events',
|
||||
gatewayApiUrl: '/gateway/api/trpc',
|
||||
gatewayWebUrl: '/gateway/',
|
||||
buildCommitSha: 'd'.repeat(40),
|
||||
});
|
||||
});
|
||||
|
||||
void it('falls back safely when the embedded script is malformed', () => {
|
||||
const config = resolveGameFrontendRuntimeConfig(documentWithConfig('{'), {});
|
||||
|
||||
assert.equal(config.appBasePath, '/');
|
||||
assert.equal(config.gameApiUrl, '/api/trpc');
|
||||
assert.equal(config.gameSseUrl, '/api/events');
|
||||
assert.equal(config.buildCommitSha, 'unknown');
|
||||
});
|
||||
});
|
||||
@@ -29,6 +29,31 @@ void describe('game frontend Vite config', () => {
|
||||
assert.equal(loaded?.config.build?.sourcemap, true);
|
||||
});
|
||||
|
||||
void it('allows a profile-neutral relative asset base without changing the application base fallback', async () => {
|
||||
const previousAssetBasePath = process.env.VITE_ASSET_BASE_PATH;
|
||||
const previousAppBasePath = process.env.VITE_APP_BASE_PATH;
|
||||
process.env.VITE_ASSET_BASE_PATH = './';
|
||||
process.env.VITE_APP_BASE_PATH = '/che';
|
||||
try {
|
||||
const configPath = path.resolve(import.meta.dirname, '../vite.config.ts');
|
||||
const loaded = await loadConfigFromFile(
|
||||
{ command: 'build', mode: 'production' },
|
||||
configPath,
|
||||
path.dirname(configPath),
|
||||
undefined,
|
||||
undefined,
|
||||
'runner'
|
||||
);
|
||||
|
||||
assert.equal(loaded?.config.base, './');
|
||||
} finally {
|
||||
if (previousAssetBasePath === undefined) delete process.env.VITE_ASSET_BASE_PATH;
|
||||
else process.env.VITE_ASSET_BASE_PATH = previousAssetBasePath;
|
||||
if (previousAppBasePath === undefined) delete process.env.VITE_APP_BASE_PATH;
|
||||
else process.env.VITE_APP_BASE_PATH = previousAppBasePath;
|
||||
}
|
||||
});
|
||||
|
||||
void it('uses the deployment-pinned full commit SHA as the displayed build version', async () => {
|
||||
const commitSha = 'ABCDEF0123456789ABCDEF0123456789ABCDEF01';
|
||||
const previousCommitSha = process.env.VITE_BUILD_COMMIT_SHA;
|
||||
|
||||
Reference in New Issue
Block a user