Files
Aislo/tools/preview_up.py
T
eomsangdonandClaude Opus 5.5 a09ac1c42d feat(모바일): 불러오는 중 판 · 빌드판 서버 · CAD 글꼴 404 (PLAN 555)
- index.html — 첫 페이지 전까지 「불러오는 중」(테마 바탕 · 저장 테마 · 시스템 어두움) · 20 s 뒤 느린 연결 안내 · favicon 요청 없앰
- tools/preview_up.py — 앱 · CAD 빌드 뒤 vite preview(포트 = 개발 포트 − 1000 · /api · /b07-cad 프록시)
- CAD 빌드에 공용 글꼴 복사 — Tailwind 가 url 을 고치지 않아 dist/assets 에서 찾던 404
- 시험 test_555_boot_loader_preview.py

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 06:56:26 +09:00

105 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""빌드판 서버(555-2) — 앱 · CAD 를 빌드하고 `vite preview` 를 띄운다(폰 · 외부 접속용).
실행: ./venv/Scripts/python.exe tools/preview_up.py (빌드 + 띄움 · 수십 초)
./venv/Scripts/python.exe tools/preview_up.py --stop (끄기만)
- 개발 서버(vite)는 파일 수백 개를 하나씩 보내 느린 연결(Tailscale · 폰)에서 첫 화면이 늦다 —
빌드판은 묶은 파일 몇 개만 보낸다.
- 포트 = 개발 포트 − 1000(메인 5173 → 4173 · 서브 5181 → 4181) · 개발 포트 · API 포트는
환경변수(AISLO_VITE_PORT · AISLO_API_PORT) > `OWNERS.md` 이 폴더 줄 > 8000 · 5173.
- /api · /b07-cad 는 같은 폴더 백엔드로 넘김(`vite.config.ts` preview) — 백엔드는 따로 켜 둠.
- 빌드 산출물 = config/node_modules/.build · CAD dist(둘 다 git 밖) · 로그 tmp/preview.log.
- 다시 부르면 옛 것을 끄고 새로 빌드해 띄움(preview 는 띄울 때의 파일 목록을 기억).
"""
import os
import re
import subprocess
import sys
import time
import urllib.request
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
TMP = os.path.join(ROOT, "tmp")
PID_FILE = os.path.join(TMP, "preview.pid")
LOG = os.path.join(TMP, "preview.log")
VITE = os.path.join(ROOT, "config", "node_modules", "vite", "bin", "vite.js")
def owners_ports() -> tuple[int, int] | None:
"""OWNERS.md 표에서 이 폴더 줄의 (API, vite) 포트 — 짝 = `.claude/dev_up.py`."""
try:
with open(os.path.join(ROOT, "OWNERS.md"), encoding="utf-8-sig") as owners:
lines = owners.read().splitlines()
except OSError:
return None
here = os.path.normcase(os.path.normpath(ROOT))
for line in lines:
cells = [cell.strip().strip("`") for cell in line.strip().strip("|").split("|")]
if len(cells) >= 5 and os.path.normcase(os.path.normpath(cells[2])) == here:
ports = re.findall(r"\d{4,5}", cells[4])
if len(ports) == 2:
return int(ports[0]), int(ports[1])
return None
def stop() -> None:
try:
with open(PID_FILE, encoding="utf-8") as f:
pid = int(f.read().strip())
except (OSError, ValueError):
return
subprocess.run(["taskkill", "/T", "/F", "/PID", str(pid)], capture_output=True, check=False)
os.remove(PID_FILE)
def run(cmd: list[str], env: dict[str, str]) -> None:
print("RUN", " ".join(cmd), flush=True)
subprocess.run(cmd, cwd=ROOT, env=env, check=True, shell=os.name == "nt" and cmd[0] == "npm")
def main() -> int:
os.makedirs(TMP, exist_ok=True)
stop()
if "--stop" in sys.argv:
print("PREVIEW=stopped")
return 0
api, vite = owners_ports() or (8000, 5173)
api = int(os.environ.get("AISLO_API_PORT") or api)
vite = int(os.environ.get("AISLO_VITE_PORT") or vite)
port = vite - 1000
env = {**os.environ, "AISLO_API_PORT": str(api), "FRONTEND_DEV_PORT": str(vite)}
run(["node", VITE, "build", "--configLoader", "runner"], env)
run(["npm", "run", "build:b07-cad"], env)
log = open(LOG, "ab") # noqa: SIM115 — 자식 프로세스가 물려받는다
flags = subprocess.DETACHED_PROCESS | subprocess.CREATE_NEW_PROCESS_GROUP
process = subprocess.Popen(
["node", VITE, "preview", "--configLoader", "runner"],
cwd=ROOT,
env=env,
stdout=log,
stderr=subprocess.STDOUT,
creationflags=flags,
)
with open(PID_FILE, "w", encoding="utf-8") as f:
f.write(str(process.pid))
url = f"http://127.0.0.1:{port}/"
for _ in range(60):
try:
urllib.request.urlopen(url, timeout=2)
print(f"PREVIEW=up {url} (API {api}) · 로그 {LOG}")
return 0
except OSError:
time.sleep(0.5)
print(f"PREVIEW=TIMEOUT — {LOG} 확인")
return 1
if __name__ == "__main__":
sys.exit(main())