Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(@angular-devkit/build-angular): support deploy URL option for browser-esbuild builder #25992

Merged
merged 1 commit into from Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -47,6 +47,11 @@ 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 @@ -239,6 +244,7 @@ export async function normalizeOptions(
deleteOutputPath,
namedChunks,
budgets,
deployUrl,
} = options;

// Return all the normalized options
Expand Down Expand Up @@ -288,6 +294,7 @@ export async function normalizeOptions(
i18nOptions,
namedChunks,
budgets: budgets?.length ? budgets : undefined,
publicPath: deployUrl ? deployUrl : undefined,
};
}

Expand Down
Expand Up @@ -10,9 +10,6 @@ import { BuilderContext } from '@angular-devkit/architect';
import { Schema as BrowserBuilderOptions } from './schema';

const UNSUPPORTED_OPTIONS: Array<keyof BrowserBuilderOptions> = [
// * Deprecated
'deployUrl',

// * Always enabled with esbuild
// 'commonChunk',

Expand Down
@@ -0,0 +1,82 @@
/**
* @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 { buildEsbuildBrowser } from '../../index';
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 */');

// 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/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/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 dynamic import statements when option is set', async () => {
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);
harness
.expectFile('dist/main.js')
.content.toContain('import("https://example.com/some/path/a');
});
});
});
Expand Up @@ -405,5 +405,6 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu
'ngJitMode': jit ? 'true' : 'false',
},
footer,
publicPath: options.publicPath,
};
}
Expand Up @@ -64,6 +64,7 @@ export function createCompilerPluginOptions(
inlineStyleLanguage,
preserveSymlinks,
tailwindConfiguration,
publicPath: options.publicPath,
},
};
}
Expand Up @@ -62,6 +62,7 @@ export function createGlobalStylesBundleOptions(
},
includePaths: stylePreprocessorOptions?.includePaths,
tailwindConfiguration,
publicPath: options.publicPath,
},
cache,
);
Expand Down
Expand Up @@ -82,6 +82,7 @@ export async function generateIndexHtml(
},
},
crossOrigin: crossOrigin,
deployUrl: buildOptions.publicPath,
});

indexHtmlGenerator.readAsset = readAsset;
Expand Down
Expand Up @@ -25,6 +25,7 @@ export interface BundleStylesheetOptions {
externalDependencies?: string[];
target: string[];
tailwindConfiguration?: { file: string; package: string };
publicPath?: string;
}

export function createStylesheetBundleOptions(
Expand Down Expand Up @@ -62,6 +63,7 @@ export function createStylesheetBundleOptions(
target: options.target,
preserveSymlinks: options.preserveSymlinks,
external: options.externalDependencies,
publicPath: options.publicPath,
conditions: ['style', 'sass'],
mainFields: ['style', 'sass'],
plugins: [
Expand Down