{"id":13580768,"url":"https://github.com/vikerman/ivy-universal","last_synced_at":"2025-04-06T02:32:46.172Z","repository":{"id":34286156,"uuid":"161606046","full_name":"vikerman/ivy-universal","owner":"vikerman","description":"Server side rendering using Angular Ivy","archived":false,"fork":false,"pushed_at":"2023-01-07T02:38:50.000Z","size":4240,"stargazers_count":179,"open_issues_count":29,"forks_count":13,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-08-02T15:45:55.124Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/vikerman.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-12-13T08:15:30.000Z","updated_at":"2024-01-13T02:43:24.000Z","dependencies_parsed_at":"2023-01-15T05:53:30.704Z","dependency_job_id":null,"html_url":"https://github.com/vikerman/ivy-universal","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikerman%2Fivy-universal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikerman%2Fivy-universal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikerman%2Fivy-universal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vikerman%2Fivy-universal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vikerman","download_url":"https://codeload.github.com/vikerman/ivy-universal/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223233260,"owners_count":17110625,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T15:01:54.921Z","updated_at":"2024-11-05T19:33:21.396Z","avatar_url":"https://github.com/vikerman.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# Ivy\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.1.1.\n\nThis is an initial test of server side rendering on top of Angular Ivy.\n\nThe base Ivy client project was generated by\n\n`ng new ivy --experimental-ivy`\n\n## Build and run the Universal application\n\n### Installation\n`npm ci`\n\n(To get the exactly pinned version in package-lock.json)\n\n## Running in prod mode (to see the actual JS payload sizes)\n`npm run start`\n\nNavigate to http://localhost:4200\n\n## Running in dev mode (for development)\n`npm run dev`\n\nNavigate to http://localhost:4200\n\nThe page will live reload when code is changed.\n\n## What's this?\n\nThe example illustrates how Angular Ivy makes the following possible\n\n1. \"Automatic\" code splitting at component and route level\n1. Server-side Rendering(SSR) with Angular Ivy\n1. Selective client side rehydration based on user events / data binding changes\n\nComing soon:\n1. Configurable load and prefetch strategies\n1. Data fetching and state transfer\n1. Server streaming?\n\n## Code organization\n\nAll the things happening server side are at https://github.com/vikerman/ivy-universal/tree/master/server\nAll 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.\n\nThe project itself relies on nightly Ivy builds with no modifications.\n\n(Though [main.ts](https://github.com/vikerman/ivy-universal/blob/master/src/main.ts), [main.server.ts](https://github.com/vikerman/ivy-universal/blob/master/src/main.server.ts) and [routes.ts](https://github.com/vikerman/ivy-universal/blob/master/src/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\".)\n\n\n## What's happening and how does it work?\n\nThe 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.\n\nOn 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:\n\n- Setup a global event handler on the document in order to buffer events.\n- Registers a shell Custom Element for every known component in the system. This does *not* load the actual component code. It just uses the component metadata to watch for property binding changes.\n\nAt this point no Angular specific code or component code has been loaded. (Current bootstrap size without polyfills: ~12 Kb)\n\nWhen 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.\n\nThe component on bootstrapping rehydrates the DOM node sent by the server using the [rehydration renderer](https://github.com/vikerman/ivy-universal/blob/master/src/lib/rehydration/rehydration_renderer.ts). 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.\n\nLet'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.\n\nThis way we can have a progressive bootstrapping strategy that loads components only on demand.\n\nThis 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.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvikerman%2Fivy-universal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvikerman%2Fivy-universal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvikerman%2Fivy-universal/lists"}