Skip to content

Commit

Permalink
fix(@angular/build): ensure correct handling of index.output for SSR
Browse files Browse the repository at this point in the history
Previously, the index file was not being renamed correctly when using server-side rendering (SSR).

Closes: angular#29012
  • Loading branch information
alan-agius4 committed Dec 3, 2024
1 parent 3d1c52b commit b5f1310
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 15 deletions.
30 changes: 16 additions & 14 deletions packages/angular/build/src/builders/application/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,24 +327,26 @@ export async function normalizeOptions(
let indexOutput: string;
// The output file will be created within the configured output path
if (typeof options.index === 'string') {
/**
* If SSR is activated, create a distinct entry file for the `index.html`.
* This is necessary because numerous server/cloud providers automatically serve the `index.html` as a static file
* if it exists (handling SSG).
*
* For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
*
* This approach can also be applied to service workers, where the `index.csr.html` is served instead of the prerendered `index.html`.
*/
const indexBaseName = path.basename(options.index);
indexOutput =
(ssrOptions || prerenderOptions) && indexBaseName === 'index.html'
? INDEX_HTML_CSR
: indexBaseName;
indexOutput = options.index;
} else {
indexOutput = options.index.output || 'index.html';
}

/**
* If SSR is activated, create a distinct entry file for the `index.html`.
* This is necessary because numerous server/cloud providers automatically serve the `index.html` as a static file
* if it exists (handling SSG).
*
* For instance, accessing `foo.com/` would lead to `foo.com/index.html` being served instead of hitting the server.
*
* This approach can also be applied to service workers, where the `index.csr.html` is served instead of the prerendered `index.html`.
*/
const indexBaseName = path.basename(indexOutput);
indexOutput =
(ssrOptions || prerenderOptions) && indexBaseName === 'index.html'
? INDEX_HTML_CSR
: indexBaseName;

indexHtmlOptions = {
input: path.join(
workspaceRoot,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@
*/

import { buildApplication } from '../../index';
import { OutputMode } from '../../schema';
import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup';

describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
describe('Option: "index"', () => {
beforeEach(async () => {
// Application code is not needed for index tests
await harness.modifyFile('src/tsconfig.app.json', (content) => {
const tsConfig = JSON.parse(content);
tsConfig.files ??= [];
tsConfig.files.push('main.server.ts', 'server.ts');

return JSON.stringify(tsConfig);
});

await harness.writeFile('src/server.ts', `console.log('Hello!');`);
await harness.writeFile('src/main.ts', 'console.log("TEST");');
});

Expand Down Expand Up @@ -227,5 +236,27 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
harness.expectFile('dist/browser/index.csr.html').toExist();
harness.expectFile('dist/browser/index.html').toNotExist();
});

it(`should generate 'index.csr.html' instead of 'index.html' when outputMode is 'Server' when 'output' is 'index.html'`, async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
outputMode: OutputMode.Server,
index: {
input: 'src/index.html',
output: 'index.html',
},
server: 'src/main.server.ts',
ssr: { entry: 'src/server.ts' },
});

const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();

harness.expectFile('dist/browser/index.csr.html').toExist();

const manifestFilePath = 'dist/server/angular-app-manifest.mjs';
harness.expectFile(manifestFilePath).content.not.toContain('index.csr.html');
harness.expectFile(manifestFilePath).content.toContain('index.html');
});
});
});

0 comments on commit b5f1310

Please sign in to comment.