mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
This commit adds a background macrotask when an XHR request is performed. The macrotask is started during `loadstart` and ended during `loadend` event. The macrotask is needed so that the application is not stabilized during HTTP calls. This is important for server rendering, as the application is rendering when the application is stabilized. The application is stabilized when there are no longer pending Macro and Micro tasks intercepted by Zone.js, Since an XHR request is none of these, we create a background macrotask so that Zone.js is made aware that there is something pending. Prior to this change, we patched the `HttpHandler` in `@angular/platform-server` but this is not enough, as there can be multiple `HttpHandler` in an application, example when importing `HttpClient` in a lazy loaded component/module. Which causes a new unpatched instance of `HttpHandler` to be created in the child injector which is not intercepted by Zone.js and thus the application is stabalized and rendered before the XHR request is finalized. NB: Zone.js is fundamental for SSR and currently, it's not possible to do SSR without it. Closes: #49425 PR Close #49546
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google LLC All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
/* tslint:disable:no-console */
|
|
require('zone.js/bundles/zone-node.umd.js');
|
|
|
|
import {enableProdMode, Type} from '@angular/core';
|
|
import {renderModule} from '@angular/platform-server';
|
|
import * as express from 'express';
|
|
|
|
import {HelloWorldServerModule} from './helloworld/app.server';
|
|
const {default: helloworld} = require('raw-loader!./helloworld/index.html');
|
|
|
|
import {TransferStateServerModule} from './transferstate/app.server';
|
|
const {default: transferstate} = require('raw-loader!./transferstate/index.html');
|
|
|
|
import {HttpLazyTransferStateServerModule} from './http-transferstate-lazy/app.server';
|
|
const {default: httptransferstatelazy} = require('raw-loader!./http-transferstate-lazy/index.html');
|
|
|
|
const app = express();
|
|
|
|
function render(moduleType: Type<any>, html: string) {
|
|
return (req, res) => {
|
|
renderModule(moduleType, {
|
|
document: html,
|
|
url: req.url,
|
|
}).then((response) => {
|
|
res.send(response);
|
|
});
|
|
};
|
|
}
|
|
|
|
enableProdMode();
|
|
|
|
// Client bundles will be statically served from the built/ directory.
|
|
app.use('/webpack-out', express.static('webpack-out'));
|
|
|
|
// Keep the browser logs free of errors.
|
|
app.get('/favicon.ico', (req, res) => {
|
|
res.send('');
|
|
});
|
|
|
|
// Mock API
|
|
app.get('/api', (req, res) => {
|
|
res.json({ data: 'API response'});
|
|
});
|
|
|
|
//-----------ADD YOUR SERVER SIDE RENDERED APP HERE ----------------------
|
|
app.get('/helloworld', render(HelloWorldServerModule, helloworld));
|
|
app.get('/transferstate', render(TransferStateServerModule, transferstate));
|
|
app.get('/http-transferstate-lazy', render(HttpLazyTransferStateServerModule, httptransferstatelazy));
|
|
|
|
app.listen(4206, () => {
|
|
console.log('Server listening on port 4206!');
|
|
});
|