This project was generated with Angular CLI version 7.1.1.
This is an initial test of server side rendering on top of Angular Ivy.
The base Ivy client project was generated by
ng new ivy --experimental-ivy
npm ci
(To get the exactly pinned version in package-lock.json)
npm run start
Navigate to http://localhost:4200
npm run dev
Navigate to http://localhost:4200
The page will live reload when code is changed.
The example illustrates how Angular Ivy makes the following possible
Coming soon:
All the things happening server side are at https://github.com/vikerman/ivy-universal/tree/master/server All the user code are in https://github.com/vikerman/ivy-universal/tree/master/src/ except for https://github.com/vikerman/ivy-universal/tree/master/src/lib which contains all the supporting code which would eventually be part of some NPM node module.
The project itself relies on nightly Ivy builds with no modifications.
(Though main.ts, main.server.ts and routes.ts are currently hand written, they would eventually be automatically generated by Angular CLI using Angular architect APIs by parsing the decorator metadata for each component. This would be the part that would make the code splitting and progressive bootstrapping "automatic".)
The webpack magic comments in https://github.com/vikerman/ivy-universal/blob/master/src/main.ts ensures that each Angular Component in the components/ and pages/ folder gets a separate chunk. The default Angular CLI webpack settings ensures that common chunks are automatcially created for any code shared between these components.
On the server the page for the current route gets rendered(more on this later). The rendered HTML is sent to the client. On the client the only code that runs is a bootstrapping code. This code does the following:
At this point no Angular specific code or component code has been loaded. (Current bootstrap size without polyfills: ~12 Kb)
When a user initiates an event (say click a button) - The global event handler walks up the DOM tree from the event target till it find what appears to be a component root. It then uses webpack loader to load the chunk corresponding to the component.
The component on bootstrapping rehydrates the DOM node sent by the server using the rehydration renderer. This lets the component become active without having to load the code for its child components because as of now they weren't required to be re-rendered.
Let's say the currently active component changes its state based on the click handler and that resulted in chaging the data binding for the child - The shell Custom Element setup for the child component recognizes that its input properties have changed. In reaction to this the child Custom Element fetches the chunk coresponding to its component. The child component in turn boots up by rehydrating on top its server generated nodes and the process continues.
This way we can have a progressive bootstrapping strategy that loads components only on demand.
This is just an illustration of one possible strategy and how rehydration of SSR nodes is useful - but with the current organization of components as individually loadable units we can now tune the load strategy that makes sense for the application. In the future configurable prefetch and load strategies will be added to the project.