Skip to content

Commit 312e572

Browse files
authored
fix(prerender): use browser builder's index option in prerender builder
Fixes #1585
1 parent 9b5ce20 commit 312e572

File tree

6 files changed

+57
-7
lines changed

6 files changed

+57
-7
lines changed

integration/express-engine-ivy-prerender/angular.json

+4-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
"options": {
4040
"progress": false,
4141
"outputPath": "dist/express-engine-ivy-prerender/browser",
42-
"index": "src/index.html",
42+
"index": {
43+
"input": "src/index.html",
44+
"output": "src/home.html"
45+
},
4346
"main": "src/main.ts",
4447
"polyfills": "src/polyfills.ts",
4548
"tsConfig": "tsconfig.app.json",

modules/builders/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ ts_library(
2424
tsconfig = ":bazel-tsconfig-build.json",
2525
deps = [
2626
"@npm//@angular-devkit/architect",
27+
"@npm//@angular-devkit/build-angular",
2728
"@npm//@angular-devkit/core",
2829
"@npm//@types/browser-sync",
2930
"@npm//browser-sync",
@@ -81,6 +82,7 @@ ng_test_library(
8182
deps = [
8283
":builders",
8384
"@npm//@angular-devkit/architect",
85+
"@npm//@angular-devkit/build-angular",
8486
"@npm//@angular-devkit/core",
8587
"@npm//@types/browser-sync",
8688
"@npm//@types/shelljs",

modules/builders/src/prerender/index.ts

+22-4
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
*/
88

99
import { BuilderContext, BuilderOutput, createBuilder, targetFromTargetString } from '@angular-devkit/architect';
10+
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
1011
import { fork } from 'child_process';
1112
import * as fs from 'fs';
1213
import * as path from 'path';
1314

1415
import { PrerenderBuilderOptions, PrerenderBuilderOutput } from './models';
15-
import { getRoutes, shardArray } from './utils';
16+
import { getIndexOutputFile, getRoutes, shardArray } from './utils';
1617

1718
type BuildBuilderOutput = BuilderOutput & {
1819
baseOutputPath: string;
@@ -67,13 +68,15 @@ async function _parallelRenderRoutes(
6768
context: BuilderContext,
6869
indexHtml: string,
6970
outputPath: string,
71+
indexFile: string,
7072
serverBundlePath: string,
7173
): Promise<void> {
7274
const workerFile = path.join(__dirname, 'render.js');
7375
const childProcesses = shardedRoutes.map(routes =>
7476
new Promise((resolve, reject) => {
7577
fork(workerFile, [
7678
indexHtml,
79+
indexFile,
7780
serverBundlePath,
7881
outputPath,
7982
...routes,
@@ -103,12 +106,15 @@ async function _renderUniversal(
103106
context: BuilderContext,
104107
browserResult: BuildBuilderOutput,
105108
serverResult: BuildBuilderOutput,
109+
browserOptions: BrowserBuilderOptions,
106110
numProcesses?: number,
107111
): Promise<BuildBuilderOutput> {
112+
// Users can specify a different base html file e.g. "src/home.html"
113+
const indexFile = getIndexOutputFile(browserOptions);
108114
// We need to render the routes for each locale from the browser output.
109115
for (const outputPath of browserResult.outputPaths) {
110-
const browserIndexOutputPath = path.join(outputPath, 'index.html');
111-
const indexHtml = fs.readFileSync(browserIndexOutputPath, 'utf8');
116+
const browserIndexInputPath = path.join(outputPath, indexFile);
117+
const indexHtml = fs.readFileSync(browserIndexInputPath, 'utf8');
112118

113119
const { baseOutputPath = '' } = serverResult;
114120
const localeDirectory = path.relative(browserResult.baseOutputPath, outputPath);
@@ -125,6 +131,7 @@ async function _renderUniversal(
125131
context,
126132
indexHtml,
127133
outputPath,
134+
indexFile,
128135
serverBundlePath,
129136
);
130137
}
@@ -152,7 +159,18 @@ export async function execute(
152159
return { success, error } as BuilderOutput;
153160
}
154161

155-
return _renderUniversal(routes, context, browserResult, serverResult, options.numProcesses);
162+
const browserTarget = targetFromTargetString(options.browserTarget);
163+
const browserOptions =
164+
await context.getTargetOptions(browserTarget) as unknown as BrowserBuilderOptions;
165+
166+
return _renderUniversal(
167+
routes,
168+
context,
169+
browserResult,
170+
serverResult,
171+
browserOptions,
172+
options.numProcesses,
173+
);
156174
}
157175

158176
export default createBuilder(execute);

modules/builders/src/prerender/render.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import * as path from 'path';
1111

1212
const [
1313
indexHtml,
14+
indexFile,
1415
serverBundlePath,
1516
browserOutputPath,
1617
...routes
@@ -50,7 +51,7 @@ async function getServerBundle(bundlePath: string) {
5051
*/
5152
(async () => {
5253
const { renderModuleFn, AppServerModuleDef } = await getServerBundle(serverBundlePath);
53-
const browserIndexOutputPath = path.join(browserOutputPath, 'index.html');
54+
const browserIndexOutputPath = path.join(browserOutputPath, indexFile);
5455
for (const route of routes) {
5556
const renderOpts = {
5657
document: indexHtml + '<!-- This page was prerendered with Angular Universal -->',

modules/builders/src/prerender/utils.spec.ts

+15-1
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77
*/
88

99
import * as Architect from '@angular-devkit/architect';
10+
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
1011
import { logging } from '@angular-devkit/core';
1112
import * as fs from 'fs';
1213
import * as guessParser from 'guess-parser';
1314

1415
import { PrerenderBuilderOptions } from './models';
15-
import { getRoutes, shardArray } from './utils';
16+
import { getIndexOutputFile, getRoutes, shardArray } from './utils';
1617

1718

1819
describe('Prerender Builder Utils', () => {
@@ -120,4 +121,17 @@ describe('Prerender Builder Utils', () => {
120121
expect(result).toEqual([[0], [1], [2], [3], [4]]);
121122
});
122123
});
124+
125+
describe('#getIndexOutputFile', () => {
126+
it('Should return only the file name when index is a string', () => {
127+
const options = { index: 'src/home.html' } as BrowserBuilderOptions;
128+
expect(getIndexOutputFile(options)).toBe('home.html');
129+
});
130+
131+
it('Should return full file path when index is an object', () => {
132+
const options =
133+
{ index: { input: 'src/index.html', output: 'src/home.html' } } as BrowserBuilderOptions;
134+
expect(getIndexOutputFile(options)).toBe('src/home.html');
135+
});
136+
});
123137
});

modules/builders/src/prerender/utils.ts

+12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
*/
88

99
import { BuilderContext, targetFromTargetString } from '@angular-devkit/architect';
10+
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
1011
import * as fs from 'fs';
1112
import { parseAngularRoutes } from 'guess-parser';
1213
import * as os from 'os';
@@ -67,3 +68,14 @@ export function shardArray<T>(items: T[], maxNoOfShards = (os.cpus().length - 1)
6768

6869
return shardedArray;
6970
}
71+
72+
/**
73+
* Returns the name of the index file outputted by the browser builder.
74+
*/
75+
export function getIndexOutputFile(options: BrowserBuilderOptions): string {
76+
if (typeof options.index === 'string') {
77+
return path.basename(options.index);
78+
} else {
79+
return options.index.output || 'index.html';
80+
}
81+
}

0 commit comments

Comments
 (0)