Framework updates
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
136
node_modules/@jqhtml/ssr/README.md
generated
vendored
136
node_modules/@jqhtml/ssr/README.md
generated
vendored
@@ -361,6 +361,142 @@ Or flush specific bundle:
|
||||
|
||||
---
|
||||
|
||||
## SSR Preload API (Hydration Acceleration)
|
||||
|
||||
The SSR Preload API eliminates redundant `on_load()` calls during client hydration. When the SSR server already fetched data for a component, the client can skip the identical fetch and use the captured data directly.
|
||||
|
||||
**Without preload:** SSR fetches data → client boots → client fetches same data again (wasted round-trip).
|
||||
|
||||
**With preload:** SSR fetches data → captures it → client receives captured data → client boots with preloaded data → no redundant fetch.
|
||||
|
||||
### Server-Side: Capturing Data
|
||||
|
||||
During SSR rendering, enable data capture to record each component's loaded data:
|
||||
|
||||
```javascript
|
||||
// 1. Enable capture before rendering
|
||||
jqhtml.start_data_capture();
|
||||
|
||||
// 2. Render the component (on_load() runs, data is captured automatically)
|
||||
// ... component renders normally ...
|
||||
|
||||
// 3. Retrieve captured data (one-shot: clears buffer after retrieval)
|
||||
const captured = jqhtml.get_captured_data();
|
||||
// Returns: [{ component: 'DashboardIndex', args: { user_id: 123 }, data: { items: [...] } }, ...]
|
||||
|
||||
// 4. Stop capture when done
|
||||
jqhtml.stop_data_capture();
|
||||
|
||||
// 5. Include captured data in SSR response
|
||||
return { html: renderedHtml, preload: captured };
|
||||
```
|
||||
|
||||
**Capture rules:**
|
||||
- Only components with `on_load()` are captured (static components excluded)
|
||||
- Deduplicates by component name + args (Load Coordinator aware)
|
||||
- `get_captured_data()` is one-shot: clears the buffer on retrieval
|
||||
- `start_data_capture()` is idempotent (safe to call multiple times)
|
||||
|
||||
### Client-Side: Injecting Preloaded Data
|
||||
|
||||
Before components boot on the client, seed the preload cache with SSR-captured data:
|
||||
|
||||
```javascript
|
||||
// 1. Inject preloaded data BEFORE components initialize
|
||||
jqhtml.set_preload_data(ssrPreloadData);
|
||||
|
||||
// 2. Components boot → _load() finds preload cache hit → skips on_load() entirely
|
||||
// ... components initialize normally, but with instant data ...
|
||||
|
||||
// 3. Clear unconsumed entries after hydration is complete
|
||||
jqhtml.clear_preload_data();
|
||||
```
|
||||
|
||||
**Preload rules:**
|
||||
- `set_preload_data(entries)` must be called before components boot
|
||||
- Each preload entry is consumed on first use (one-shot per key)
|
||||
- `set_preload_data(null)` or `set_preload_data([])` is a no-op
|
||||
- `clear_preload_data()` removes any unconsumed entries
|
||||
|
||||
### Complete Data Flow
|
||||
|
||||
```
|
||||
SSR Server:
|
||||
1. jqhtml.start_data_capture()
|
||||
2. Render component (on_load() fetches data → CAPTURED)
|
||||
3. captured = jqhtml.get_captured_data()
|
||||
4. Return { html, preload: captured }
|
||||
|
||||
Client:
|
||||
1. jqhtml.set_preload_data(ssr_preload)
|
||||
2. Components boot → _load() hits preload cache → skips on_load()
|
||||
3. jqhtml.clear_preload_data()
|
||||
```
|
||||
|
||||
### Updated PHP Integration Example (with Preload)
|
||||
|
||||
```php
|
||||
// Usage with preload data
|
||||
$ssr = new JqhtmlSSR();
|
||||
$result = $ssr->render('Dashboard_Index_Action', ['user_id' => 123], $bundles);
|
||||
|
||||
if ($result['status'] === 'success') {
|
||||
$html = $result['payload']['html'];
|
||||
$preload = json_encode($result['payload']['preload'] ?? []);
|
||||
|
||||
echo $html;
|
||||
echo "<script>jqhtml.set_preload_data({$preload});</script>";
|
||||
echo "<script src='/bundles/vendor.js'></script>";
|
||||
echo "<script src='/bundles/app.js'></script>";
|
||||
echo "<script>jqhtml.boot().then(() => jqhtml.clear_preload_data());</script>";
|
||||
}
|
||||
```
|
||||
|
||||
### Updated Node.js Client Example (with Preload)
|
||||
|
||||
```javascript
|
||||
const response = await sendSSRRequest(9876, {
|
||||
id: 'render-1',
|
||||
type: 'render',
|
||||
payload: {
|
||||
bundles: [
|
||||
{ id: 'vendor', content: vendorBundleContent },
|
||||
{ id: 'app', content: appBundleContent }
|
||||
],
|
||||
component: 'Dashboard_Index_Action',
|
||||
args: { user_id: 123 },
|
||||
options: { baseUrl: 'http://localhost:3000' }
|
||||
}
|
||||
});
|
||||
|
||||
const { html, preload } = response.payload;
|
||||
|
||||
// Embed preload data in the page for client-side hydration
|
||||
const pageHtml = `
|
||||
${html}
|
||||
<script>
|
||||
jqhtml.set_preload_data(${JSON.stringify(preload || [])});
|
||||
</script>
|
||||
<script src="/bundles/vendor.js"></script>
|
||||
<script src="/bundles/app.js"></script>
|
||||
<script>
|
||||
jqhtml.boot().then(() => jqhtml.clear_preload_data());
|
||||
</script>
|
||||
`;
|
||||
```
|
||||
|
||||
### API Reference
|
||||
|
||||
| Method | Description |
|
||||
|--------|-------------|
|
||||
| `jqhtml.start_data_capture()` | Enable data capture mode (idempotent) |
|
||||
| `jqhtml.get_captured_data()` | Returns captured entries and clears buffer (one-shot) |
|
||||
| `jqhtml.stop_data_capture()` | Stops capture and clears all capture state |
|
||||
| `jqhtml.set_preload_data(entries)` | Seeds preload cache with SSR-captured data |
|
||||
| `jqhtml.clear_preload_data()` | Clears unconsumed preload entries |
|
||||
|
||||
---
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user