Skip to content

Commit fc5a2af

Browse files
clydinalan-agius4
authored andcommitted
refactor(@angular-devkit/build-angular): remove Webpack helpers from application builder option normalization
The usage of several Webpack-centric option helper functions has now been removed from the `application` builder. This allows for more efficient processing of incoming options but also removes additional imports across builder code.
1 parent b20dcae commit fc5a2af

File tree

1 file changed

+61
-30
lines changed
  • packages/angular_devkit/build_angular/src/builders/application

1 file changed

+61
-30
lines changed

packages/angular_devkit/build_angular/src/builders/application/options.ts

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,20 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import { BuilderContext } from '@angular-devkit/architect';
9+
import type { BuilderContext } from '@angular-devkit/architect';
1010
import type { Plugin } from 'esbuild';
1111
import { realpathSync } from 'node:fs';
1212
import { access, constants } from 'node:fs/promises';
1313
import { createRequire } from 'node:module';
1414
import path from 'node:path';
15-
import {
16-
globalScriptsByBundleName,
17-
normalizeGlobalStyles,
18-
} from '../../tools/webpack/utils/helpers';
1915
import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils';
2016
import { colors } from '../../utils/color';
2117
import { useJSONBuildLogs } from '../../utils/environment-options';
2218
import { I18nOptions, createI18nOptions } from '../../utils/i18n-options';
2319
import { IndexHtmlTransform } from '../../utils/index-file/index-html-generator';
2420
import { normalizeCacheOptions } from '../../utils/normalize-cache';
25-
import { generateEntryPoints } from '../../utils/package-chunk-sort';
2621
import { loadPostcssConfiguration } from '../../utils/postcss-configuration';
2722
import { findTailwindConfigurationFile } from '../../utils/tailwind';
28-
import { getIndexInputFile, getIndexOutputFile } from '../../utils/webpack-browser-config';
2923
import {
3024
Schema as ApplicationBuilderOptions,
3125
I18NTranslation,
@@ -194,35 +188,29 @@ export async function normalizeOptions(
194188
? undefined
195189
: await getTailwindConfig(workspaceRoot, projectRoot, context);
196190

197-
const globalStyles: { name: string; files: string[]; initial: boolean }[] = [];
198-
if (options.styles?.length) {
199-
const { entryPoints: stylesheetEntrypoints, noInjectNames } = normalizeGlobalStyles(
200-
options.styles || [],
201-
);
202-
for (const [name, files] of Object.entries(stylesheetEntrypoints)) {
203-
globalStyles.push({ name, files, initial: !noInjectNames.includes(name) });
204-
}
205-
}
206-
207-
const globalScripts: { name: string; files: string[]; initial: boolean }[] = [];
208-
if (options.scripts?.length) {
209-
for (const { bundleName, paths, inject } of globalScriptsByBundleName(options.scripts)) {
210-
globalScripts.push({ name: bundleName, files: paths, initial: inject });
211-
}
212-
}
191+
const globalStyles = normalizeGlobalEntries(options.styles, 'styles');
192+
const globalScripts = normalizeGlobalEntries(options.scripts, 'scripts');
213193

214194
let indexHtmlOptions;
215195
// index can never have a value of `true` but in the schema it's of type `boolean`.
216196
if (typeof options.index !== 'boolean') {
217197
indexHtmlOptions = {
218-
input: path.join(workspaceRoot, getIndexInputFile(options.index)),
198+
input: path.join(
199+
workspaceRoot,
200+
typeof options.index === 'string' ? options.index : options.index.input,
201+
),
219202
// The output file will be created within the configured output path
220-
output: getIndexOutputFile(options.index),
221-
// TODO: Use existing information from above to create the insertion order
222-
insertionOrder: generateEntryPoints({
223-
scripts: options.scripts ?? [],
224-
styles: options.styles ?? [],
225-
}),
203+
output:
204+
typeof options.index === 'string'
205+
? path.basename(options.index)
206+
: options.index.output || 'index.html',
207+
insertionOrder: [
208+
['polyfills', true],
209+
...globalStyles.filter((s) => s.initial).map((s) => [s.name, false]),
210+
...globalScripts.filter((s) => s.initial).map((s) => [s.name, false]),
211+
['main', true],
212+
// [name, esm]
213+
] as [string, boolean][],
226214
transformer: extensions?.indexHtmlTransformer,
227215
// Preload initial defaults to true
228216
preloadInitial: typeof options.index !== 'object' || (options.index.preloadInitial ?? true),
@@ -462,3 +450,46 @@ function normalizeDirectoryPath(path: string): string {
462450

463451
return path;
464452
}
453+
454+
function normalizeGlobalEntries(
455+
rawEntries: ({ bundleName?: string; input: string; inject?: boolean } | string)[] | undefined,
456+
defaultName: string,
457+
): { name: string; files: string[]; initial: boolean }[] {
458+
if (!rawEntries?.length) {
459+
return [];
460+
}
461+
462+
const bundles = new Map<string, { name: string; files: string[]; initial: boolean }>();
463+
464+
for (const rawEntry of rawEntries) {
465+
let entry;
466+
if (typeof rawEntry === 'string') {
467+
// string entries use default bundle name and inject values
468+
entry = { input: rawEntry };
469+
} else {
470+
entry = rawEntry;
471+
}
472+
473+
const { bundleName, input, inject = true } = entry;
474+
475+
// Non-injected entries default to the file name
476+
const name = bundleName || (inject ? defaultName : path.basename(input, path.extname(input)));
477+
478+
const existing = bundles.get(name);
479+
if (!existing) {
480+
bundles.set(name, { name, files: [input], initial: inject });
481+
continue;
482+
}
483+
484+
if (existing.initial !== inject) {
485+
throw new Error(
486+
`The "${name}" bundle is mixing injected and non-injected entries. ` +
487+
'Verify that the project options are correct.',
488+
);
489+
}
490+
491+
existing.files.push(input);
492+
}
493+
494+
return [...bundles.values()];
495+
}

0 commit comments

Comments
 (0)