What are the key deployment challenges for combined server-side rendered apps compared to deploying separate front-end and back-end services?
Generally deploying a unified project that contains both backend APIs and the front-ends that consume them is that you actually guarantee you'll have a match between the two, simplifying APIs dramatically. It's when you don't have control of a client (such as a mobile or desktop app) that we see the biggest problems with deployments of one or the other significantly messing things up.If you did need a decoupled client, then you would just need to follow the same versioning guidelines and follow the same compatibility best practices.
When adding custom API code into Angular's server.ts file, how do you keep things organized for bigger, more complex projects?
Folllow the same best practices that you would in any ExpressJS or other API process. Generally I like to have a single simple entrypoint that includes references to the major modules of an application (users, posts, reviews, purchases, etc). You can use simple TypeScript imports and exports and a reasonable folder structure to make this much more manageable.I'm also a fan of things like NestJS that act as a framework for building these types of backends using a component structure that was inspired by Angular.
What's the best way to manage complex application or user state between the server-rendered page and the interactive client-side app?
Generally state transfer is handled automatically for you part of hydration. For pages where first-load performance is critical, I recommend turning off HTTP caching, allowing you to send down less state. In this way you send down only the rendered HTML and not the backing data behind it. The data will be fetch again client-side as part of bootstrap, but this doesn't block the initial load. The default way caches this and prevents the client-side HTTP request.Here's a sample app config that turns off this HTTP Caching with
withNoHttpTransferCache
.export const appConfig: ApplicationConfig = {
providers: [
Title,
PostService,
AdminService,
provideBrowserGlobalErrorListeners(),
provideZonelessChangeDetection(),
provideCheckNoChangesConfig({ exhaustive: true, interval: 1000 }),
provideRouter(routes),
provideClientHydration(withEventReplay(), withNoHttpTransferCache()),
provideHttpClient(withFetch()),
],
};