M9: PWA — 홈 화면에 추가, 오프라인 안내
- 매니페스트·아이콘(192/512/maskable/apple-touch, scripts/pwa-icons.ts로 다시 만들기) - 손으로 쓴 서비스 워커(apps/web/sw.js): 빌드 때 Vite 플러그인이 빌드 ID를 넣음. 페이지는 네트워크만(오프라인이면 offline.html), /assets/*만 캐시 먼저(200개까지), /api·/ws·/healthz·/internal은 손대지 않음 - 오프라인 안내 페이지, 방 밖에서도 "인터넷 연결이 없어요" 띠 - 홈 아래 "홈 화면에 추가" 카드(설치 버튼, iOS는 공유 메뉴 안내, 닫으면 기억) - 테스트: apps/web/src/sw.test.ts, e2e/pwa.e2e.ts(E2E_PORT), a11y.e2e.ts도 E2E_PORT 읽기 - 문서: 07 §11, 11 배포(no-cache 대상), README 확인 목록 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,26 @@
|
||||
import { defineConfig } from 'vite';
|
||||
import { createHash } from 'node:crypto';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { defineConfig, type Plugin } from 'vite';
|
||||
import react from '@vitejs/plugin-react';
|
||||
|
||||
/** Emits dist/sw.js with a build id, so a deploy that changes files installs a new worker (docs/07 §11). */
|
||||
function serviceWorker(): Plugin {
|
||||
return {
|
||||
name: 'bg-service-worker',
|
||||
apply: 'build',
|
||||
generateBundle(_, bundle) {
|
||||
const src = readFileSync(new URL('./sw.js', import.meta.url), 'utf8');
|
||||
const offline = readFileSync(new URL('./public/offline.html', import.meta.url), 'utf8');
|
||||
const files = Object.keys(bundle).sort().join('\n');
|
||||
const build = createHash('sha256').update(src).update(offline).update(files).digest('hex').slice(0, 12);
|
||||
if (!src.includes("'__BUILD__'")) throw new Error('sw.js: VERSION placeholder missing');
|
||||
this.emitFile({ type: 'asset', fileName: 'sw.js', source: src.replace("'__BUILD__'", `'${build}'`) });
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
plugins: [react(), serviceWorker()],
|
||||
server: {
|
||||
port: 5173,
|
||||
proxy: {
|
||||
|
||||
Reference in New Issue
Block a user