Skip to content

Commit

Permalink
fix(@angular-devkit/build-angular): service-worker references non-exi…
Browse files Browse the repository at this point in the history
…stent named index output

This commit addresses an issue where the service worker incorrectly referenced a non-existent `index.html` when utilizing the output index option. Additionally, it ensures proper resolution of the service worker configuration when the option value is set to `true`.
  • Loading branch information
alan-agius4 committed Mar 25, 2024
1 parent 31e8ad3 commit c71e954
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 2 deletions.
Expand Up @@ -153,10 +153,12 @@ export async function executePostBundleSteps(
workspaceRoot,
serviceWorker,
options.baseHref || '/',
options.indexHtmlOptions?.output,
// Ensure additional files recently added are used
[...outputFiles, ...additionalOutputFiles],
assetFiles,
);

additionalOutputFiles.push(
createOutputFileFromText(
'ngsw.json',
Expand Down
Expand Up @@ -326,8 +326,12 @@ export async function normalizeOptions(
fileReplacements,
globalStyles,
globalScripts,
serviceWorker:
typeof serviceWorker === 'string' ? path.join(workspaceRoot, serviceWorker) : undefined,
serviceWorker: serviceWorker
? path.join(
workspaceRoot,
typeof serviceWorker === 'string' ? serviceWorker : 'src/ngsw-config.json',
)
: undefined,
indexHtmlOptions,
tailwindConfiguration,
postcssConfiguration,
Expand Down
@@ -0,0 +1,92 @@
/**
* @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
*/

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

describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
describe('Option: "serviceWorker"', () => {
beforeEach(async () => {
const manifest = {
index: '/index.html',
assetGroups: [
{
name: 'app',
installMode: 'prefetch',
resources: {
files: ['/favicon.ico', '/index.html'],
},
},
{
name: 'assets',
installMode: 'lazy',
updateMode: 'prefetch',
resources: {
files: [
'/assets/**',
'/*.(svg|cur|jpg|jpeg|png|apng|webp|avif|gif|otf|ttf|woff|woff2)',
],
},
},
],
};

await harness.writeFile('src/ngsw-config.json', JSON.stringify(manifest));
});

it('should not generate SW config when option is unset', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
serviceWorker: undefined,
});

const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
harness.expectFile('dist/browser/ngsw.json').toNotExist();
});

it('should not generate SW config when option is false', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
serviceWorker: false,
});

const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
harness.expectFile('dist/browser/ngsw.json').toNotExist();
});

it('should generate SW config when option is true', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
serviceWorker: true,
});

const { result } = await harness.executeOnce();
expect(result?.success).toBeTrue();
harness.expectFile('dist/browser/ngsw.json').toExist();
});

it('should generate SW config referencing index output', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
serviceWorker: true,
index: {
input: 'src/index.html',
output: 'index.csr.html',
},
});

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

const config = await harness.readFile('dist/browser/ngsw.json');
expect(JSON.parse(config)).toEqual(jasmine.objectContaining({ index: '/index.csr.html' }));
});
});
});
Expand Up @@ -180,6 +180,7 @@ export async function augmentAppWithServiceWorkerEsbuild(
workspaceRoot: string,
configPath: string,
baseHref: string,
indexHtml: string | undefined,
outputFiles: BuildOutputFile[],
assetFiles: BuildOutputAsset[],
): Promise<{ manifest: string; assetFiles: BuildOutputAsset[] }> {
Expand All @@ -188,6 +189,10 @@ export async function augmentAppWithServiceWorkerEsbuild(
try {
const configurationData = await fsPromises.readFile(configPath, 'utf-8');
config = JSON.parse(configurationData) as Config;

if (indexHtml) {
config.index = indexHtml;
}
} catch (error) {
assertIsError(error);
if (error.code === 'ENOENT') {
Expand Down

0 comments on commit c71e954

Please sign in to comment.