diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts index dcc9bccc6496..cdcb41122498 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/index.ts @@ -242,7 +242,6 @@ export function serveWebpackBrowser( baseHref: browserOptions.baseHref, root: context.workspaceRoot, projectRoot, - outputPath: path.join(context.workspaceRoot, browserOptions.outputPath), ngswConfigPath: browserOptions.ngswConfigPath, }), ); diff --git a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve_service-worker_spec.ts b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve_service-worker_spec.ts index 13e80c7058c6..bbd5872ad711 100644 --- a/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve_service-worker_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/dev-server/tests/behavior/serve_service-worker_spec.ts @@ -42,6 +42,23 @@ describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { }; describe('Behavior: "dev-server builder serves service worker"', () => { + beforeEach(() => { + harness.useProject('test', { + root: '.', + sourceRoot: 'src', + cli: { + cache: { + enabled: false, + }, + }, + i18n: { + sourceLocale: { + 'code': 'fr', + }, + }, + }); + }); + it('works with service worker', async () => { setupBrowserTarget(harness, { serviceWorker: true, @@ -99,13 +116,38 @@ describeBuilder(serveWebpackBrowser, DEV_SERVER_BUILDER_INFO, (harness) => { hashTable: { '/favicon.ico': '84161b857f5c547e3699ddfbffc6d8d737542e01', '/assets/folder-asset.txt': '617f202968a6a81050aa617c2e28e1dca11ce8d4', - '/index.html': 'cb8ad8c81cd422699d6d831b6f25ad4481f2c90a', + '/index.html': '9d232e3e13b4605d197037224a2a6303dd337480', '/spectrum.png': '8d048ece46c0f3af4b598a95fd8e4709b631c3c0', }, }), ); }); + it('works with localize', async () => { + setupBrowserTarget(harness, { + serviceWorker: true, + assets: ['src/favicon.ico', 'src/assets'], + styles: ['src/styles.css'], + localize: ['fr'], + }); + + await harness.writeFiles({ + 'ngsw-config.json': JSON.stringify(manifest), + 'src/assets/folder-asset.txt': 'folder-asset.txt', + 'src/styles.css': `body { background: url(./spectrum.png); }`, + }); + + harness.useTarget('serve', { + ...BASE_OPTIONS, + }); + + const { result, response } = await executeOnceAndFetch(harness, '/ngsw.json'); + + expect(result?.success).toBeTrue(); + + expect(await response?.json()).toBeDefined(); + }); + it('works in watch mode', async () => { setupBrowserTarget(harness, { serviceWorker: true, diff --git a/packages/angular_devkit/build_angular/src/webpack/plugins/service-worker-plugin.ts b/packages/angular_devkit/build_angular/src/webpack/plugins/service-worker-plugin.ts index 0e32faf3749a..8d556ae7e365 100644 --- a/packages/angular_devkit/build_angular/src/webpack/plugins/service-worker-plugin.ts +++ b/packages/angular_devkit/build_angular/src/webpack/plugins/service-worker-plugin.ts @@ -12,7 +12,6 @@ import { augmentAppWithServiceWorker } from '../../utils/service-worker'; export interface ServiceWorkerPluginOptions { projectRoot: string; root: string; - outputPath: string; baseHref?: string; ngswConfigPath?: string; } @@ -21,8 +20,16 @@ export class ServiceWorkerPlugin { constructor(private readonly options: ServiceWorkerPluginOptions) {} apply(compiler: Compiler) { - compiler.hooks.done.tapPromise('angular-service-worker', async (_compilation) => { - const { projectRoot, root, baseHref = '', ngswConfigPath, outputPath } = this.options; + compiler.hooks.done.tapPromise('angular-service-worker', async ({ compilation }) => { + const { projectRoot, root, baseHref = '', ngswConfigPath } = this.options; + // We use the output path from the compilation instead of build options since during + // localization the output path is modified to a temp directory. + // See: https://github.com/angular/angular-cli/blob/7e64b1537d54fadb650559214fbb12707324cd75/packages/angular_devkit/build_angular/src/utils/i18n-options.ts#L251-L252 + const outputPath = compilation.outputOptions.path; + + if (!outputPath) { + throw new Error('Compilation output path cannot be empty.'); + } await augmentAppWithServiceWorker( projectRoot,