diff --git a/Makefile b/Makefile index c362996..360a7dd 100644 --- a/Makefile +++ b/Makefile @@ -32,10 +32,44 @@ help: @echo "Available targets:" @grep -hE '^[a-zA-Z0-9_-]+:' $(MAKEFILE_LIST) | cut -d: -f1 | sed 's/^/ /' +# Frontend sources whose changes must trigger a rebuild. `backend/static/index.html` +# doubles as the build stamp, so a clean clone or `make clean` (which empties +# backend/static) forces the next build to regenerate. +FRONTEND_OUT := backend/static/index.html + +# `npm ci` is only needed when the manifest/lockfile change. +FRONTEND_DEPS_STAMP := frontend/node_modules/.install-stamp + +# Build the SvelteKit bundle and copy it into backend/static (embedded via +# go:embed). Incremental: recompile only when frontend sources are newer than the +# embedded bundle. Paths are checked from the recipe (not as make prerequisites) +# because SvelteKit route names like `(app)` break make's filename parsing. frontend: - cd frontend && npm ci && npm run build - rm -rf backend/static/* - cp -r frontend/build/* backend/static/ + @set -e; \ + if [ ! -f $(FRONTEND_DEPS_STAMP) ] \ + || [ frontend/package.json -nt $(FRONTEND_DEPS_STAMP) ] \ + || [ frontend/package-lock.json -nt $(FRONTEND_DEPS_STAMP) ]; then \ + echo '> cd frontend && npm ci'; \ + cd frontend && npm ci; \ + touch node_modules/.install-stamp; \ + cd ..; \ + fi; \ + if [ ! -f $(FRONTEND_OUT) ] \ + || [ -n "$$(find frontend/src frontend/static -newer $(FRONTEND_OUT) -print -quit)" ] \ + || [ frontend/package.json -nt $(FRONTEND_OUT) ] \ + || [ frontend/package-lock.json -nt $(FRONTEND_OUT) ] \ + || [ frontend/svelte.config.js -nt $(FRONTEND_OUT) ] \ + || [ frontend/vite.config.ts -nt $(FRONTEND_OUT) ] \ + || [ frontend/tailwind.config.ts -nt $(FRONTEND_OUT) ] \ + || [ frontend/tsconfig.json -nt $(FRONTEND_OUT) ]; then \ + echo '> cd frontend && npm run build'; \ + cd frontend && npm run build; \ + cd ..; \ + rm -rf backend/static/*; \ + cp -r frontend/build/* backend/static/; \ + else \ + echo 'frontend: up to date'; \ + fi backend: mkdir -p bin @@ -87,7 +121,7 @@ build-release: frontend cp bin/galo bin/galo-$(VERSION) @echo "release: bin/galo-$(VERSION)" -run: backend +run: frontend backend ./bin/galo migrate: diff --git a/README.md b/README.md index 060616c..5ef8d4b 100644 --- a/README.md +++ b/README.md @@ -125,7 +125,7 @@ make build # frontend -> backend/static -> go:embed -> bin/galo Отдельные шаги: ```bash -make frontend # npm ci && npm run build, копирует статику в backend/static +make frontend # npm run build, копирует статику в backend/static (инкрементально) make backend # CGO_ENABLED=0 go build -tags nodynamic -o bin/galo ``` @@ -133,6 +133,10 @@ make backend # CGO_ENABLED=0 go build -tags nodynamic -o bin/galo > транспилированный в Go libwebp вместо динамической загрузки через purego, > благодаря чему бинарник остаётся полностью статическим. +`make frontend` собирает только при изменении исходников `frontend/`; `npm ci` +запускается лишь когда менялись `package.json`/`package-lock.json`. `make run` +и `make build` учитывают это и не пересобирают неизменившийся фронтенд. + Проверка: ```bash @@ -151,7 +155,7 @@ make migrate # go run ./cmd/migrate — применяет up-миграци ## Локальный запуск ```bash -make run # соберёт backend и запустит ./bin/galo +make run # доберёт изменившийся фронтенд, соберёт backend и запустит ./bin/galo # или напрямую: ./bin/galo ```