Skip to content

Commit

Permalink
feat(@nguniversal/builders): add ng-server-context for SSG pages
Browse files Browse the repository at this point in the history
This provides an easy way to distinguish between SSR, SSG, and client-side apps (CSR).

Closes #2612
  • Loading branch information
alan-agius4 committed Oct 12, 2022
1 parent a62d3d3 commit fef00f9
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 18 deletions.
2 changes: 1 addition & 1 deletion integration/express-engine-ivy-hybrid/e2e/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ export async function waitForAppRootElement(): Promise<boolean> {

export async function isPrerendered(): Promise<boolean> {
const src = await browser.driver.getPageSource();
return src.includes('This page was prerendered with Angular Universal');
return src.includes('ng-server-context="ssg"');
}
2 changes: 2 additions & 0 deletions modules/builders/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ ts_library(
"@npm//@angular-devkit/architect",
"@npm//@angular-devkit/build-angular",
"@npm//@angular-devkit/core",
"@npm//@angular/core",
"@npm//@angular/platform-server",
"@npm//@types/browser-sync",
"@npm//@types/express",
"@npm//guess-parser",
Expand Down
14 changes: 7 additions & 7 deletions modules/builders/src/prerender/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('Prerender Builder', () => {
);

expect(content).toContain('foo works!');
expect(content).toContain('This page was prerendered with Angular Universal');
expect(content).toContain('ng-server-context="ssg"');
await run.stop();
});

Expand Down Expand Up @@ -109,13 +109,13 @@ describe('Prerender Builder', () => {
);

expect(appContent).toContain('app app is running!');
expect(appContent).toContain('This page was prerendered with Angular Universal');
expect(appContent).toContain('ng-server-context="ssg"');

expect(fooContent).toContain('foo works!');
expect(fooContent).toContain('This page was prerendered with Angular Universal');
expect(fooContent).toContain('ng-server-context="ssg"');

expect(fooBarContent).toContain('foo-bar works!');
expect(fooBarContent).toContain('This page was prerendered with Angular Universal');
expect(fooBarContent).toContain('ng-server-context="ssg"');

await run.stop();
});
Expand Down Expand Up @@ -151,13 +151,13 @@ describe('Prerender Builder', () => {
expect(output.success).toBe(true);

expect(appContent).toContain('app app is running!');
expect(appContent).toContain('This page was prerendered with Angular Universal');
expect(appContent).toContain('ng-server-context="ssg"');

expect(fooContent).toContain('foo works!');
expect(fooContent).toContain('This page was prerendered with Angular Universal');
expect(fooContent).toContain('ng-server-context="ssg"');

expect(fooBarContent).toContain('foo-bar works!');
expect(fooBarContent).toContain('This page was prerendered with Angular Universal');
expect(fooBarContent).toContain('ng-server-context="ssg"');

await run.stop();
});
Expand Down
30 changes: 22 additions & 8 deletions modules/builders/src/prerender/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/

import type { Type } from '@angular/core';
import type * as platformServer from '@angular/platform-server';
import assert from 'assert';
import * as fs from 'fs';
import * as path from 'path';
import { loadEsmModule } from '../utils/utils';
Expand Down Expand Up @@ -41,28 +44,39 @@ export async function render({
const outputFolderPath = path.join(outputPath, route);
const outputIndexPath = path.join(outputFolderPath, 'index.html');

const { renderModule, AppServerModule } = await import(serverBundlePath);
const { AppServerModule, renderModule, ɵSERVER_CONTEXT } = (await import(serverBundlePath)) as {
renderModule: typeof platformServer.renderModule | undefined;
ɵSERVER_CONTEXT: typeof platformServer.ɵSERVER_CONTEXT | undefined;
AppServerModule: Type<unknown> | undefined;
};

assert(renderModule, `renderModule was not exported from: ${serverBundlePath}.`);
assert(AppServerModule, `AppServerModule was not exported from: ${serverBundlePath}.`);
assert(ɵSERVER_CONTEXT, `ɵSERVER_CONTEXT was not exported from: ${serverBundlePath}.`);

const indexBaseName = fs.existsSync(path.join(outputPath, 'index.original.html'))
? 'index.original.html'
: indexFile;
const browserIndexInputPath = path.join(outputPath, indexBaseName);
let indexHtml = await fs.promises.readFile(browserIndexInputPath, 'utf8');
indexHtml = indexHtml.replace(
'</html>',
'<!-- This page was prerendered with Angular Universal -->\n</html>',
);
let document = await fs.promises.readFile(browserIndexInputPath, 'utf8');

if (inlineCriticalCss) {
// Workaround for https://github.com/GoogleChromeLabs/critters/issues/64
indexHtml = indexHtml.replace(
document = document.replace(
/ media="print" onload="this\.media='all'"><noscript><link .+?><\/noscript>/g,
'>',
);
}

let html = await renderModule(AppServerModule, {
document: indexHtml,
document,
url: route,
extraProviders: [
{
provide: ɵSERVER_CONTEXT,
useValue: 'ssg',
},
],
});

if (inlineCriticalCss) {
Expand Down
2 changes: 0 additions & 2 deletions modules/builders/testing/hello-world-app/src/main.server.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { enableProdMode } from '@angular/core';

import { environment } from './environments/environment';

if (environment.production) {
enableProdMode();
}

export { AppServerModule } from './app/app.server.module';
export { renderModule } from '@angular/platform-server';

0 comments on commit fef00f9

Please sign in to comment.