feat: Server-side rendering support for demo apps#48
Open
PieterjanDeClippel wants to merge 14 commits into
Open
feat: Server-side rendering support for demo apps#48PieterjanDeClippel wants to merge 14 commits into
PieterjanDeClippel wants to merge 14 commits into
Conversation
Add SSR via MintPlayer.AspNetCore.SpaServices.Routing prerendering with aspnet-prerendering Node.js bridge and @angular/platform-server. Per-app changes: - .NET: AddSpaPrerenderingService, UseImprovedHsts, UseSpaPrerendering, SpaPrerenderingService with OnSupplyData hook - Angular: server build target, main.server.ts with BootstrapContext, split app.config into shared/browser/server configs, DATA_FROM_SERVER token Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- BuildRoutes registers home, po/{type} (list), po/{type}/{id} (detail)
- OnSupplyData loads PersistentObject from DB for detail route
- SparkPoDetailComponent: uses SPARK_SERVER_DATA on server, skips API calls
- SparkQueryListComponent: skips data loading on server
- Guard window.history.back() with !isPlatformServer
- Add SPARK_SERVER_DATA token to ng-spark library
- Provide SPARK_SERVER_DATA in each app's main.server.ts
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The paramMap subscription doesn't emit during SSR, so the server data was never applied. Move isPlatformServer check to ngOnInit which runs synchronously before the server render completes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The template requires both item() AND entityType() to render attributes. Previously only persistentObject was supplied, so the @if (entityType()) block was skipped and no attributes appeared in the page source. Now OnSupplyData passes entityTypes and entityType alongside the persistentObject, and ngOnInit sets all three signals on the server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Supply programUnits in OnSupplyData for all routes so the shell sidebar renders server-side. Shell components read from SPARK_SERVER_DATA on the server and skip API calls. Also convert SpaPrerenderingService classes to use [Inject] attribute with partial classes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Supply query, entityType, entityTypes, and queryItems in OnSupplyData for the po-list route. SparkQueryListComponent reads from SPARK_SERVER_DATA on the server so the table renders in the page source. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…helper
The query-list page (/query/companies) wasn't matched by BuildRoutes
because only po/{type} was registered. Add query/{queryId} route and
extract SupplyQueryListData helper used by both query-list and po-list
cases.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Most query JSON files lack the entityType property, and the source property name (e.g. "Companies") doesn't match the entity type name (e.g. "Company") — especially for irregular plurals like People/Person. Use SparkContext reflection (same approach as GetProgramUnits endpoint) to map property names to entity types via their generic type argument. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues caused TranslatedString to render as [Object object]:
1. aspnet-prerendering uses Newtonsoft.Json which doesn't know about
the System.Text.Json TranslatedStringJsonConverter, so it serialized
as {"translations":{"en":"value"}} instead of {"en":"value"}.
Fix: Add TranslatedStringNewtonsoftJsonConverter and register it
via JsonConvert.DefaultSettings in AddSpark().
2. The currentLanguage signal wasn't set during SSR.
Fix: Pass data["language"] resolved from Accept-Language headers
via IRequestCultureResolver (falls back to culture.json default),
and set currentLanguage signal in main.server.ts before rendering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…l links canRead/canCreate/canDelete/canEdit defaulted to false in ng-spark components, so permission-gated elements (links, buttons) were missing from SSR HTML. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Register edit route in SpaPrerenderingService, hydrate entity type and persistent object from server data in spark-po-edit, and guard spark-po-form API calls from running during SSR. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…nce) Supply LookupReference and Reference option data from the server during SSR so that <select> elements render with all their options when JS is disabled. - Add SupplyFormOptionsAsync to all 3 demo SpaPrerenderingService files - Inject ILookupReferenceService, load lookup values for editable attrs - Execute queries for Reference attributes to populate dropdown options - Pass server data through po-edit -> po-form via new inputs - Add case-insensitive key remapping in po-form ngOnInit to handle camelCase dictionary keys from JSON serialization - Add [attr.selected] on <option> elements for correct SSR pre-selection - Add PRD document for the feature Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #38
aspnet-prerenderingNode.js bridge with@angular/platform-serverfor Angular server renderingSpaPrerenderingService.OnSupplyDatahook ready for loading PersistentObjects from DB during SSRChanges
Root (npm):
@angular/platform-server,reflect-metadata,@angular-devkit/build-angular,aspnet-prerenderingPer-app .NET:
MintPlayer.AspNetCore.SpaServices.Routing,MintPlayer.AspNetCore.HstsProgram.cs:AddSpaPrerenderingService,UseImprovedHsts, conditionalUseSpaStaticFilesImproved,UseSpaPrerenderingServices/SpaPrerenderingService.cswithOnSupplyDatahookPer-app Angular:
angular.json: Addedserverarchitect target (@angular-devkit/build-angular:server)tsconfig.server.json: ESNext module + bundler resolution (supports ng-bootstrap subpath exports)main.server.ts: Server entry withcreateServerRenderer,BootstrapContext(Angular 21)app.config.tsinto shared/browser/server configsDATA_FROM_SERVERinjection token for server-supplied databuild:ssrnpm scriptTest plan
npm run build:ssrsucceeds in each ClientApp directory🤖 Generated with Claude Code