maplestory/frontend/src/features/registry.js
caadiq 7ebfe4a449 홈 메뉴 카드 hover 시 기능 페이지 chunk prefetch
React.lazy 로 분할된 feature 번들을 메뉴 카드 hover/focus 시점에 미리
fetch 해서, 클릭→네비게이션 시점에는 이미 로드되어 있도록 함.
Suspense 깜빡임(~0.5s) 제거.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 20:48:43 +09:00

83 lines
2.4 KiB
JavaScript

/**
* 기능 자동 등록 시스템
*
* - features/{kebab-case}/pc/{PascalCase}.jsx : PC 사용자 페이지
* - features/{kebab-case}/pc/{PascalCase}Admin.jsx: PC 관리자 페이지
* - features/{kebab-case}/tablet/{PascalCase}.jsx : 태블릿 사용자 페이지
* - features/{kebab-case}/mobile/{PascalCase}.jsx : 모바일 사용자 페이지
*/
import { lazy } from 'react'
const pages = import.meta.glob('./*/{pc,tablet,mobile}/*.jsx')
function slugToPascal(slug) {
return slug
.split('-')
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
.join('')
}
const userPcCache = new Map()
const adminPcCache = new Map()
const userTabletCache = new Map()
const userMobileCache = new Map()
function loadCached(cache, slug, device, suffix) {
if (cache.has(slug)) return cache.get(slug)
const pascal = slugToPascal(slug)
const path = `./${slug}/${device}/${pascal}${suffix}.jsx`
const loader = pages[path]
const component = loader ? lazy(loader) : null
cache.set(slug, component)
return component
}
/**
* slug에 해당하는 PC 사용자 페이지 컴포넌트 반환
*/
export function getUserComponent(slug) {
return loadCached(userPcCache, slug, 'pc', '')
}
/**
* slug에 해당하는 관리자 페이지 컴포넌트 반환 (PC 전용)
*/
export function getAdminComponent(slug) {
return loadCached(adminPcCache, slug, 'pc', 'Admin')
}
/**
* slug에 해당하는 태블릿 사용자 페이지 컴포넌트 반환
*/
export function getTabletComponent(slug) {
return loadCached(userTabletCache, slug, 'tablet', '')
}
/**
* slug에 해당하는 모바일 사용자 페이지 컴포넌트 반환
*/
export function getMobileComponent(slug) {
return loadCached(userMobileCache, slug, 'mobile', '')
}
/**
* slug에 해당하는 관리자 페이지가 존재하는지
*/
export function hasAdminPage(slug) {
if (!slug) return false
const cleaned = slug.replace(/^\/+/, '').split('/')[0]
return getAdminComponent(cleaned) !== null
}
/**
* chunk prefetch: 렌더 트리거 없이 동적 import 만 시작
* 메뉴 카드 hover 시 호출해 네비게이션 직후 Suspense 깜빡임을 제거.
*/
export function prefetchUserComponent(slug) {
if (!slug) return
const cleaned = slug.replace(/^\/+/, '').split('/')[0]
const pascal = slugToPascal(cleaned)
const loader = pages[`./${cleaned}/pc/${pascal}.jsx`]
if (loader) loader()
}