ApiGW
GraphQL
HTTP
Server Components
Tailwind
Inline SVG
(getting the data)
(presenting the data)
Record
Playback
Expose
Connect
type Backend = {
getTopModelsAwards():Promise<CompetitionPageData>;
getAwards():Promise<CompetitionPageData>;
list(superCat:SuperCategory, filter:Filter):Promise<ListPageData>;
chatPage(displayName:DisplayName):Promise<ChatPageData>;
// ...
}class ApiGwBackend implements Backend {
getTopModelsAwards():Promise<CompetitionPageData> { ... }
getAwards():Promise<CompetitionPageData> { ... }
list(superCat:SuperCategory, filter:Filter):Promise<ListPageData> { ... }
chatPage(displayName:DisplayName):Promise<ChatPageData> { ... }
// ...
}ApiGW
GraphQL
HTTP
interface App {
route(path:UrlPath):VDom | Error | Redirect;
frame():VDom;
renderToString(res:VDom):string;
report(path: UrlPath, error: Error):VDom;
}class LiveJasmin implements App {
constructor(backend:Backend) { ... }
// interface implementation here ...
}Record
https://livejasmin.com/en/girls
Expose
Connect
Playback
Hydrate
ApiGW
https://livejasmin.com/en/girls
(empty)
Render
ApiGW
Record
https://livejasmin.com/en/girls
Playback
ApiGW
Hydrate
| SPA | Hybrid |
|---|---|
| ✅no application servers required | ✅ application servers only have to deal with initial response |
| ❌ suboptimal SEO | ❌ more data loaded |
| ❌ initial loading more visible | ❌ less opportunity for caching |
| ❌ more JavaScript shipped | ❌ more JavaScript shipped |
npm i : 15s, npm run build : 2sMetrics for list page PoC: