Fix bin/publish: use correct .env path for rspade_system Fix bin/publish script: prevent grep exit code 1 from terminating script 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
94 lines
3.4 KiB
Markdown
Executable File
94 lines
3.4 KiB
Markdown
Executable File
# SSR Full Page Cache (FPC) Implementation Plan
|
|
|
|
## Overview
|
|
Server-side rendered static page caching system using Playwright + Redis. Routes marked with `#[Static_Page]` auto-generate and serve pre-rendered HTML to unauthenticated users.
|
|
|
|
## Implementation Order
|
|
|
|
### Phase 1: Foundation & Research
|
|
1. Study `rsx:debug` command and Playwright script structure
|
|
2. Understand current Dispatch.php flow and route attribute processing
|
|
|
|
### Phase 2: Core Commands
|
|
3. Create `rsx:ssr_fpc:create` command (copy from `rsx:debug`)
|
|
4. Create Playwright script `generate-static-cache.js` in command's resource directory
|
|
5. Implement exclusive lock `GENERATE_STATIC_CACHE` in Playwright script
|
|
6. Strip GET parameters from URL before rendering
|
|
7. Handle redirect interception (manual redirect mode)
|
|
8. Capture response: DOM + headers OR redirect location
|
|
9. Generate cache structure with 30-char ETag (SHA1 of build_key + URL + content)
|
|
|
|
### Phase 3: Storage Layer
|
|
10. Implement Redis cache with key format: `ssr_fpc:{build_key}:{sha1(url)}`
|
|
11. Store JSON: `{url, code, page_dom/redirect, build_key, etag, generated_at}`
|
|
12. Add comprehensive error logging to `storage/logs/ssr-fpc-errors.log`
|
|
|
|
### Phase 4: Runtime Integration
|
|
13. Update `Session::__is_fpc_client()` with header check: `X-RSpade-FPC-Client: 1`
|
|
14. Add header to Playwright script
|
|
15. Create `#[Static_Page]` attribute stub in `.vscode/attribute-stubs.php`
|
|
16. Modify Dispatch.php to:
|
|
- Check for `#[Static_Page]` attribute
|
|
- Verify `!Session::is_active()` (unauthenticated only)
|
|
- Skip FPC if `Session::__is_fpc_client()` is true
|
|
- Check Redis cache, generate if missing (fatal on failure)
|
|
- Validate ETag for 304 responses
|
|
- Serve with proper cache headers (0s dev, 5min prod)
|
|
|
|
### Phase 5: Management & Config
|
|
17. Create `rsx:ssr_fpc:reset` command (flush Redis `ssr_fpc:*` keys)
|
|
18. Add config to `config/rsx.php`:
|
|
```php
|
|
'ssr_fpc' => [
|
|
'enabled' => env('SSR_FPC_ENABLED', false),
|
|
'generation_timeout' => 30000, // ms
|
|
]
|
|
```
|
|
|
|
### Phase 6: Documentation
|
|
19. Create `app/RSpade/man/ssr_fpc.txt` with:
|
|
- Purpose and usage
|
|
- Attribute syntax
|
|
- Cache lifecycle
|
|
- Bypass headers
|
|
- Future roadmap (sitemap, parallelization, external service, shared secret)
|
|
- Security considerations
|
|
|
|
### Phase 7: Testing
|
|
20. Test simple static page generation and serving
|
|
21. Test redirect caching and serving
|
|
22. Test ETag validation (304 responses)
|
|
23. Test authenticated user bypass
|
|
24. Test cache invalidation on build_key change
|
|
|
|
## Key Technical Decisions
|
|
|
|
### Redis Cache Key
|
|
Format: `ssr_fpc:{build_key}:{sha1(request_path)}`
|
|
- Auto-invalidates on deployment (build_key changes)
|
|
- URL hash prevents key collisions
|
|
- GET params stripped before hashing
|
|
|
|
### ETag
|
|
First 30 chars of SHA1(build_key + url + content)
|
|
|
|
### FPC Client Header
|
|
`X-RSpade-FPC-Client: 1`
|
|
|
|
### Session Check
|
|
`Session::is_active()` (not `RsxAuth::check()`)
|
|
|
|
### Redirect Handling
|
|
Cache first 302, don't follow
|
|
|
|
### Cache TTL
|
|
Indefinite (Redis LRU handles eviction)
|
|
|
|
## Future Roadmap (Not in Initial Implementation)
|
|
- Option for `rsx:ssr_fpc:create --from-sitemap` rather than a specific url
|
|
- Shared, private, automatic key for the fpc runner, so the fpc headers are only recognized by the server itself
|
|
- The same should be done for `rsx:debug`
|
|
- External service to generate the fpc renderings
|
|
- Parallelization
|
|
- Programmatic cache reset for things like updating cms or blog posts
|