Skip to content
This repository was archived by the owner on Nov 22, 2024. It is now read-only.

Commit

Permalink
feat(builders): support service worker generation with prerendering
Browse files Browse the repository at this point in the history
Closes: #1505
  • Loading branch information
alan-agius4 committed Nov 5, 2020
1 parent fb1428a commit 66e6805
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 1 deletion.
1 change: 1 addition & 0 deletions modules/builders/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ jasmine_node_test(
"@npm//@angular/compiler",
"@npm//@angular/platform-browser",
"@npm//@angular/platform-browser-dynamic",
"@npm//@angular/service-worker",
"@npm//@types/node",
"@npm//browser-sync",
"@npm//express",
Expand Down
36 changes: 35 additions & 1 deletion modules/builders/src/prerender/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { Architect } from '@angular-devkit/architect';
import { join, virtualFs } from '@angular-devkit/core';
import { join, normalize, virtualFs } from '@angular-devkit/core';
import { createArchitect, host, outputPathBrowser } from '../../testing/utils';

describe('Prerender Builder', () => {
Expand Down Expand Up @@ -159,4 +159,38 @@ describe('Prerender Builder', () => {

await run.stop();
});

it('should generate service-worker', async () => {
const manifest = {
index: '/index.html',
assetGroups: [
{
name: 'app',
installMode: 'prefetch',
resources: {
files: [
'/index.html',
],
},
},
],
};

host.writeMultipleFiles({
'ngsw-config.json': JSON.stringify(manifest),
});

const run = await architect.scheduleTarget(target, { routes: ['foo'], browserTarget: 'app:build:sw' });
const output = await run.result;
expect(output.success).toBe(true);

const content = virtualFs.fileBufferToString(
host.scopedSync().read(join(outputPathBrowser, 'foo/index.html'))
);

expect(content).toContain('foo works!');
expect(content).toContain('This page was prerendered with Angular Universal');
expect(host.scopedSync().exists(normalize('dist/app/browser/ngsw.json'))).toBeTrue();
await run.stop();
});
});
36 changes: 36 additions & 0 deletions modules/builders/src/prerender/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

import { BuilderContext, BuilderOutput, createBuilder, targetFromTargetString } from '@angular-devkit/architect';
import { BrowserBuilderOptions } from '@angular-devkit/build-angular';
import { augmentAppWithServiceWorker } from '@angular-devkit/build-angular/src/utils/service-worker';
import { normalize, resolve as resolvePath } from '@angular-devkit/core';
import { NodeJsSyncHost } from '@angular-devkit/core/node';
import { fork } from 'child_process';
import * as fs from 'fs';
import * as ora from 'ora';
Expand Down Expand Up @@ -109,6 +112,19 @@ async function _renderUniversal(
browserOptions: BrowserBuilderOptions,
numProcesses?: number,
): Promise<PrerenderBuilderOutput> {
const host = new NodeJsSyncHost();
const projectName = context.target && context.target.project;
if (!projectName) {
throw new Error('The builder requires a target.');
}

const root = normalize(context.workspaceRoot);
const projectMetadata = await context.getProjectMetadata(projectName);
const projectRoot = resolvePath(
root,
normalize((projectMetadata.root as string) || ''),
);

// Users can specify a different base html file e.g. "src/home.html"
const indexFile = getIndexOutputFile(browserOptions);
// We need to render the routes for each locale from the browser output.
Expand Down Expand Up @@ -142,6 +158,26 @@ async function _renderUniversal(
}

spinner.succeed(`Prerendering routes to ${outputPath} complete.`);

if (browserOptions.serviceWorker) {
spinner.start('Generating service worker...');
try {
await augmentAppWithServiceWorker(
host,
root,
projectRoot,
normalize(outputPath),
browserOptions.baseHref || '/',
browserOptions.ngswConfigPath,
);
} catch (error) {
spinner.fail('Service worker generation failed.');

return { success: false, error: error.message };
}

spinner.succeed('Service worker generation complete.');
}
}

return browserResult;
Expand Down
3 changes: 3 additions & 0 deletions modules/builders/testing/hello-world-app/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
"scripts": []
},
"configurations": {
"sw": {
"serviceWorker": true
},
"production": {
"fileReplacements": [
{
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"@angular/platform-browser-dynamic": "^11.0.0-rc.0",
"@angular/platform-server": "^11.0.0-rc.0",
"@angular/router": "^11.0.0-rc.0",
"@angular/service-worker": "^11.0.0-rc.0",
"@bazel/bazelisk": "1.7.3",
"@bazel/buildifier": "3.5.0",
"@bazel/hide-bazel-files": "1.7.0",
Expand Down
7 changes: 7 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,13 @@
dependencies:
tslib "^2.0.0"

"@angular/service-worker@^11.0.0-rc.0":
version "11.0.0-rc.2"
resolved "https://registry.yarnpkg.com/@angular/service-worker/-/service-worker-11.0.0-rc.2.tgz#a9f34190ce86fe8de2fd53fa4b4549541674c06c"
integrity sha512-rWh9EtXfFjl8riov4q+ET94mXJGxGb5KH4LwOfKN/4TKCYyfx03QVyChDH9GxRnolq6sjSeKhI9c0ni3n7dvjA==
dependencies:
tslib "^2.0.0"

"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a"
Expand Down

0 comments on commit 66e6805

Please sign in to comment.