Skip to content

Commit

Permalink
feat(@angular-devkit/build-angular): add deployUrl to application b…
Browse files Browse the repository at this point in the history
…uilder

This commit adds the deployUrl option ot the application builder.

Closes #26411
  • Loading branch information
alan-agius4 committed Mar 4, 2024
1 parent 14189b2 commit 9ca3a54
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 54 deletions.
3 changes: 1 addition & 2 deletions goldens/public-api/angular_devkit/build_angular/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface ApplicationBuilderOptions {
[key: string]: string;
};
deleteOutputPath?: boolean;
deployUrl?: string;
externalDependencies?: string[];
extractLicenses?: boolean;
fileReplacements?: FileReplacement_2[];
Expand Down Expand Up @@ -94,7 +95,6 @@ export interface BrowserBuilderOptions {
commonChunk?: boolean;
crossOrigin?: CrossOrigin;
deleteOutputPath?: boolean;
// @deprecated
deployUrl?: string;
extractLicenses?: boolean;
fileReplacements?: FileReplacement[];
Expand Down Expand Up @@ -351,7 +351,6 @@ export interface ServerBuilderOptions {
assets?: AssetPattern_4[];
buildOptimizer?: boolean;
deleteOutputPath?: boolean;
// @deprecated
deployUrl?: string;
externalDependencies?: string[];
extractLicenses?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,6 @@ interface InternalOptions {
* This is only used by the development server which currently only supports a single locale per build.
*/
forceI18nFlatOutput?: boolean;

/**
* Allows for usage of the deprecated `deployUrl` option with the compatibility builder `browser-esbuild`.
*/
deployUrl?: string;
}

/** Full set of options for `application` builder. */
Expand Down Expand Up @@ -345,7 +340,7 @@ export async function normalizeOptions(
i18nOptions,
namedChunks,
budgets: budgets?.length ? budgets : undefined,
publicPath: deployUrl ? deployUrl : undefined,
publicPath: deployUrl,
plugins: extensions?.codePlugins?.length ? extensions?.codePlugins : undefined,
loaderExtensions,
jsonLogs: useJSONBuildLogs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
"type": "string",
"description": "The full path for the TypeScript configuration file, relative to the current workspace."
},
"deployUrl": {
"type": "string",
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
},
"scripts": {
"description": "Global scripts to be included in the build.",
"type": "array",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
/**
* @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: "deployUrl"', () => {
beforeEach(async () => {
// Add a global stylesheet to test link elements
await harness.writeFile('src/styles.css', '/* Global styles */');

// Reduce the input index HTML to a single line to simplify comparing
await harness.writeFile(
'src/index.html',
'<html><head><base href="/"></head><body><app-root></app-root></body></html>',
);
});

it('should update script src and link href attributes when option is set to relative URL', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
styles: ['src/styles.css'],
deployUrl: 'deployUrl/',
});

const { result } = await harness.executeOnce();
expect(result?.success).toBe(true);
harness
.expectFile('dist/browser/index.html')
.content.toEqual(
`<html><head><base href="/"><link rel="stylesheet" href="deployUrl/styles.css"></head>` +
`<body><app-root></app-root>` +
`<script src="deployUrl/main.js" type="module"></script></body></html>`,
);
});

it('should update script src and link href attributes when option is set to absolute URL', async () => {
harness.useTarget('build', {
...BASE_OPTIONS,
styles: ['src/styles.css'],
deployUrl: 'https://example.com/some/path/',
});

const { result } = await harness.executeOnce();
expect(result?.success).toBe(true);
harness
.expectFile('dist/browser/index.html')
.content.toEqual(
`<html><head><base href="/"><link rel="stylesheet" href="https://example.com/some/path/styles.css"></head>` +
`<body><app-root></app-root>` +
`<script src="https://example.com/some/path/main.js" type="module"></script></body></html>`,
);
});

it('should update resources component stylesheets to reference deployURL', async () => {
await harness.writeFile('src/app/test.svg', '<svg></svg>');
await harness.writeFile(
'src/app/app.component.css',
`* { background-image: url('./test.svg'); }`,
);

harness.useTarget('build', {
...BASE_OPTIONS,
deployUrl: 'https://example.com/some/path/',
});

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

harness
.expectFile('dist/browser/main.js')
.content.toContain('background-image: url("https://example.com/some/path/media/test.svg")');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,7 @@
},
"deployUrl": {
"type": "string",
"description": "URL where files will be deployed.",
"x-deprecated": "Use \"baseHref\" option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url."
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
},
"verbose": {
"type": "boolean",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ import { BASE_OPTIONS, BROWSER_BUILDER_INFO, describeBuilder } from '../setup';
describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => {
describe('Option: "deployUrl"', () => {
beforeEach(async () => {
// Application code is not needed for asset tests
await harness.writeFile('src/main.ts', 'console.log("TEST");');

// Add a global stylesheet to test link elements
await harness.writeFile('src/styles.css', '/* Global styles */');

Expand Down Expand Up @@ -61,22 +58,24 @@ describeBuilder(buildEsbuildBrowser, BROWSER_BUILDER_INFO, (harness) => {
);
});

it('should update dynamic import statements when option is set', async () => {
it('should update resources component stylesheets to reference deployURL', async () => {
await harness.writeFile('src/app/test.svg', '<svg></svg>');
await harness.writeFile(
'src/app/app.component.css',
`* { background-image: url('./test.svg'); }`,
);

harness.useTarget('build', {
...BASE_OPTIONS,
styles: ['src/styles.css'],
deployUrl: 'https://example.com/some/path/',
namedChunks: true,
});

await harness.writeFile('src/main.ts', 'console.log("TEST");\nimport("./a");\nexport {}');
await harness.writeFile('src/a.ts', 'console.log("A");\nexport {}');

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

harness
.expectFile('dist/main.js')
.content.toContain('import("https://example.com/some/path/a');
.content.toContain('background-image: url("https://example.com/some/path/media/test.svg")');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,7 @@
},
"deployUrl": {
"type": "string",
"description": "URL where files will be deployed.",
"x-deprecated": "Use \"baseHref\" option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url."
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
},
"verbose": {
"type": "boolean",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,7 @@
},
"deployUrl": {
"type": "string",
"description": "URL where files will be deployed.",
"x-deprecated": "Use \"baseHref\" browser builder option, \"APP_BASE_HREF\" DI token or a combination of both instead. For more information, see https://angular.io/guide/deployment#the-deploy-url."
"description": "Customize the base path for the URLs of resources in 'index.html' and component stylesheets. This option is only necessary for specific deployment scenarios, such as with Angular Elements or when utilizing different CDN locations."
},
"vendorChunk": {
"type": "boolean",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@
*/

import { workspaces } from '@angular-devkit/core';
import {
Rule,
SchematicContext,
SchematicsException,
chain,
externalSchematic,
} from '@angular-devkit/schematics';
import { Rule, SchematicsException, chain, externalSchematic } from '@angular-devkit/schematics';
import { dirname, join } from 'node:path/posix';
import { JSONFile } from '../../utility/json-file';
import { TreeWorkspaceHost, allTargetOptions, getWorkspace } from '../../utility/workspace';
Expand Down Expand Up @@ -52,11 +46,6 @@ export default function (): Rule {
const hasServerTarget = project.targets.has('server');

for (const [, options] of allTargetOptions(buildTarget, false)) {
// Show warnings for using no longer supported options
if (usesNoLongerSupportedOptions(options, context, name)) {
continue;
}

if (options['index'] === '') {
options['index'] = false;
}
Expand Down Expand Up @@ -102,7 +91,6 @@ export default function (): Rule {
}

// Delete removed options
delete options['deployUrl'];
delete options['vendorChunk'];
delete options['commonChunk'];
delete options['resourcesOutputPath'];
Expand Down Expand Up @@ -204,19 +192,3 @@ export default function (): Rule {
return chain(rules);
};
}

function usesNoLongerSupportedOptions(
{ deployUrl, resourcesOutputPath }: Record<string, unknown>,
context: SchematicContext,
projectName: string,
): boolean {
let hasUsage = false;
if (typeof deployUrl === 'string') {
hasUsage = true;
context.logger.warn(
`Skipping migration for project "${projectName}". "deployUrl" option is not available in the application builder.`,
);
}

return hasUsage;
}

0 comments on commit 9ca3a54

Please sign in to comment.