Skip to content

Commit 443955d

Browse files
committed
fixup! feat(@angular/build): add library builder
1 parent 2369bab commit 443955d

3 files changed

Lines changed: 10 additions & 145 deletions

File tree

‎packages/angular/build/src/builders/library/pipeline/build-action.ts‎

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@ import { constants, copyFile, mkdir, writeFile } from 'node:fs/promises';
1111
import path from 'node:path';
1212
import { emitFilesToDisk } from '../../../tools/esbuild/utils';
1313
import { toPosixPath } from '../../../utils/path';
14-
import type { NormalizedEntryPoint, NormalizedLibraryOptions } from '../options';
14+
import type { NormalizedLibraryOptions } from '../options';
1515
import { collectAssetsToEmit } from './assets';
1616
import { type BundleEntryPointInput, type BundleResult, bundleEntryPoints } from './bundler';
1717
import { type SingleProgramCache, compileLibrary } from './compilation';
18-
import { type EntryPointLookup, createEntryDirectoryLookup } from './entry-points';
1918
import { generatePackageManifests } from './package-manifests';
2019
import type { createComponentStylesheetBundlerForLibrary } from './stylesheet-bundler';
2120
import type { OutputFile } from './utils';
@@ -31,7 +30,6 @@ export interface SingleBuildState {
3130
hasCompilationError?: boolean;
3231
hasEmittedManifests?: boolean;
3332
hasEmittedAssets?: boolean;
34-
entryDirectoryLookup?: EntryPointLookup;
3533
directoryExists: Set<string>;
3634
}
3735

@@ -131,29 +129,16 @@ export async function buildAction(actionContext: BuildActionContext): Promise<vo
131129
pendingChangedDtsFiles.add(file);
132130
}
133131

134-
const findEntryPoint = (buildState.entryDirectoryLookup ??= createEntryDirectoryLookup(
135-
options.entryPoints.values(),
136-
));
137132
const itemsToBundle: BundleEntryPointInput[] = [];
138133

139134
for (const entryPoint of options.entryPoints.values()) {
140135
const previousBundleResult = buildState.previousBundleResults.get(entryPoint.name);
141136
const hasEsmChanges =
142137
!previousBundleResult ||
143-
hasEntryPointChanges(
144-
entryPoint,
145-
previousBundleResult.esmModuleIds,
146-
findEntryPoint,
147-
pendingChangedEsmFiles,
148-
);
138+
hasEntryPointChanges(previousBundleResult.esmModuleIds, pendingChangedEsmFiles);
149139
const hasDtsChanges =
150140
!previousBundleResult ||
151-
hasEntryPointChanges(
152-
entryPoint,
153-
previousBundleResult.dtsModuleIds,
154-
findEntryPoint,
155-
pendingChangedDtsFiles,
156-
);
141+
hasEntryPointChanges(previousBundleResult.dtsModuleIds, pendingChangedDtsFiles);
157142

158143
if (hasEsmChanges || hasDtsChanges) {
159144
context.logger.info(`Compiling ${entryPoint.displayName}...`);
@@ -170,7 +155,7 @@ export async function buildAction(actionContext: BuildActionContext): Promise<vo
170155
let warnings: string[];
171156
try {
172157
[bundleOutput, warnings] = await Promise.all([
173-
bundleEntryPoints(itemsToBundle, esmFiles, dtsFiles, options, findEntryPoint),
158+
bundleEntryPoints(itemsToBundle, esmFiles, dtsFiles, options),
174159
diagnosePromise,
175160
]);
176161
} catch (error) {
@@ -240,17 +225,15 @@ export function hasModifiedWatchedFile(
240225
}
241226

242227
function hasEntryPointChanges(
243-
entryPoint: NormalizedEntryPoint,
244228
moduleIds: ReadonlySet<string>,
245-
findEntryPoint: EntryPointLookup,
246229
changedFiles: ReadonlySet<string>,
247230
): boolean {
248231
if (changedFiles.size === 0) {
249232
return false;
250233
}
251234

252235
for (const file of changedFiles) {
253-
if (moduleIds.has(file) || findEntryPoint(file) === entryPoint) {
236+
if (moduleIds.has(file)) {
254237
return true;
255238
}
256239
}

‎packages/angular/build/src/builders/library/pipeline/bundler.ts‎

Lines changed: 5 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
import { dts } from 'rolldown-plugin-dts';
1919
import { toPosixPath } from '../../../utils/path';
2020
import type { NormalizedEntryPoint, NormalizedLibraryOptions } from '../options';
21-
import { type EntryPointLookup, createEntryDirectoryLookup } from './entry-points';
2221
import {
2322
FESM_OUTPUT_DIR,
2423
type MemoryOutputFile,
@@ -87,15 +86,13 @@ interface MultiBundleOutput {
8786
* @param esmFiles Map of virtual ESM output file paths to their content.
8887
* @param dtsFiles Map of virtual TypeScript declaration file paths to their content.
8988
* @param options The normalized library builder options.
90-
* @param findEntryPoint Optional lookup function to find an entry point by file path.
9189
* @returns A promise resolving to the bundled output files and bundle cache results.
9290
*/
9391
export async function bundleEntryPoints(
9492
items: readonly BundleEntryPointInput[],
9593
esmFiles: ReadonlyMap<string, string>,
9694
dtsFiles: ReadonlyMap<string, string>,
9795
options: NormalizedLibraryOptions,
98-
findEntryPoint: EntryPointLookup = createEntryDirectoryLookup(options.entryPoints.values()),
9996
): Promise<BundleEntryPointsOutput> {
10097
const bundleResults = new Map<string, BundleResult>();
10198
if (items.length === 0) {
@@ -115,8 +112,8 @@ export async function bundleEntryPoints(
115112
}
116113

117114
const [esmOutput, dtsOutput] = await Promise.all([
118-
bundleAllEsm(esmEntryPoints, esmFiles, options, findEntryPoint),
119-
bundleAllDts(dtsEntryPoints, dtsFiles, options, findEntryPoint),
115+
bundleAllEsm(esmEntryPoints, esmFiles, options),
116+
bundleAllDts(dtsEntryPoints, dtsFiles, options),
120117
]);
121118

122119
for (const { entryPoint, previousBundleResult } of items) {
@@ -139,8 +136,6 @@ export async function bundleEntryPoints(
139136
};
140137
}
141138

142-
export { type EntryPointLookup, createEntryDirectoryLookup };
143-
144139
/**
145140
* Generates the Rolldown input mapping object from the specified entry points.
146141
*
@@ -170,14 +165,12 @@ function resolveEntryInputMap(
170165
* @param files Map of virtual file paths to their content.
171166
* @param extensions Candidate extensions to probe when resolving extensionless module specifiers.
172167
* @param includeMap Whether source map files should also be loaded from the memory map.
173-
* @param findEntryPoint Lookup function to identify the entry point owning a file path.
174168
* @returns A Rolldown plugin instance.
175169
*/
176170
function createMemoryFileLoaderPlugin(
177171
files: ReadonlyMap<string, string>,
178172
extensions: readonly string[],
179173
includeMap: boolean,
180-
findEntryPoint: EntryPointLookup,
181174
): Plugin {
182175
return {
183176
name: 'memory-file-loader',
@@ -217,15 +210,6 @@ function createMemoryFileLoaderPlugin(
217210
}
218211
}
219212

220-
const importerEp = findEntryPoint(importerPosix);
221-
const targetEp = findEntryPoint(resolvedCandidate ?? resolved);
222-
if (importerEp && targetEp && importerEp.name !== targetEp.name) {
223-
throw new Error(
224-
`Entry point '${importerEp.name}' cannot import '${id}' from sibling entry point directly. ` +
225-
`Import using the entry point package name instead.`,
226-
);
227-
}
228-
229213
if (resolvedCandidate) {
230214
return { id: resolvedCandidate, external: false };
231215
}
@@ -247,27 +231,6 @@ function createMemoryFileLoaderPlugin(
247231
};
248232
}
249233

250-
/**
251-
* Resolves the bundle prefix name for a shared chunk based on the entry point owning its modules.
252-
*
253-
* @param findEntryPoint Lookup function to identify entry points of module IDs.
254-
* @param moduleIds List of module IDs contained within the chunk.
255-
* @returns The bundle name if a containing entry point was found, otherwise undefined.
256-
*/
257-
function resolveChunkBundleName(
258-
findEntryPoint: EntryPointLookup,
259-
moduleIds: readonly string[],
260-
): string | undefined {
261-
for (const modId of moduleIds) {
262-
const ep = findEntryPoint(modId);
263-
if (ep) {
264-
return ep.bundleName;
265-
}
266-
}
267-
268-
return undefined;
269-
}
270-
271234
/**
272235
* Processes Rolldown output assets and chunks, extracting emitted files and computing
273236
* the transitive set of module IDs belonging to each entry point bundle.
@@ -352,7 +315,6 @@ async function executeMultiBundle(
352315
preserveSymlinks: boolean,
353316
extension: 'mjs' | 'd.ts',
354317
sourcemap: boolean,
355-
findEntryPoint: EntryPointLookup,
356318
): Promise<MultiBundleOutput> {
357319
const isDts = extension === 'd.ts';
358320
const dir = isDts ? TYPES_OUTPUT_DIR : FESM_OUTPUT_DIR;
@@ -373,12 +335,7 @@ async function executeMultiBundle(
373335
format: 'es',
374336
dir,
375337
entryFileNames: `[name].${extension}`,
376-
chunkFileNames: (chunk) => {
377-
const bundleName = resolveChunkBundleName(findEntryPoint, chunk.moduleIds);
378-
const prefix = bundleName ? `${bundleName}-` : '';
379-
380-
return `${prefix}[name]-[hash].${extension}`;
381-
},
338+
chunkFileNames: `[name]-[hash].${extension}`,
382339
sourcemap,
383340
hoistTransitiveImports: false,
384341
comments: { jsdoc: isDts, legal: true, annotation: true },
@@ -396,26 +353,23 @@ async function executeMultiBundle(
396353
* @param entryPoints The entry points to bundle.
397354
* @param esmFiles Map of virtual ESM output file paths to contents.
398355
* @param options The normalized library options.
399-
* @param findEntryPoint Lookup function to resolve entry point ownership.
400356
* @returns A promise resolving to the multi-bundle output.
401357
*/
402358
async function bundleAllEsm(
403359
entryPoints: readonly NormalizedEntryPoint[],
404360
esmFiles: ReadonlyMap<string, string>,
405361
options: NormalizedLibraryOptions,
406-
findEntryPoint: EntryPointLookup,
407362
): Promise<MultiBundleOutput> {
408363
if (entryPoints.length === 0) {
409364
return { filesToEmit: [], moduleIdsByBundle: new Map() };
410365
}
411366

412367
return executeMultiBundle(
413368
resolveEntryInputMap(entryPoints, false),
414-
[createMemoryFileLoaderPlugin(esmFiles, ESM_EXTENSIONS, true, findEntryPoint)],
369+
[createMemoryFileLoaderPlugin(esmFiles, ESM_EXTENSIONS, true)],
415370
options.preserveSymlinks,
416371
'mjs',
417372
true,
418-
findEntryPoint,
419373
);
420374
}
421375

@@ -425,14 +379,12 @@ async function bundleAllEsm(
425379
* @param entryPoints The entry points to bundle.
426380
* @param dtsFiles Map of virtual declaration output file paths to contents.
427381
* @param options The normalized library options.
428-
* @param findEntryPoint Lookup function to resolve entry point ownership.
429382
* @returns A promise resolving to the multi-bundle output.
430383
*/
431384
async function bundleAllDts(
432385
entryPoints: readonly NormalizedEntryPoint[],
433386
dtsFiles: ReadonlyMap<string, string>,
434387
options: NormalizedLibraryOptions,
435-
findEntryPoint: EntryPointLookup,
436388
): Promise<MultiBundleOutput> {
437389
if (entryPoints.length === 0) {
438390
return { filesToEmit: [], moduleIdsByBundle: new Map() };
@@ -459,13 +411,9 @@ async function bundleAllDts(
459411

460412
return executeMultiBundle(
461413
resolveEntryInputMap(entryPoints, true),
462-
[
463-
createMemoryFileLoaderPlugin(dtsFiles, DTS_EXTENSIONS, dtsSourcemap, findEntryPoint),
464-
...dtsPlugins,
465-
],
414+
[createMemoryFileLoaderPlugin(dtsFiles, DTS_EXTENSIONS, dtsSourcemap), ...dtsPlugins],
466415
options.preserveSymlinks,
467416
'd.ts',
468417
dtsSourcemap,
469-
findEntryPoint,
470418
);
471419
}

‎packages/angular/build/src/builders/library/pipeline/entry-points.ts‎

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
* found in the LICENSE file at https://angular.dev/license
77
*/
88

9-
import path from 'node:path';
10-
import { toPosixPath } from '../../../utils/path';
11-
129
export interface NormalizedEntryPoint {
1310
/** The subpath in package.json exports (e.g. '.' or './testing'). */
1411
subpath: string;
@@ -29,69 +26,6 @@ export interface NormalizedEntryPoint {
2926
isPrimary: boolean;
3027
}
3128

32-
/**
33-
* Function that resolves a file path to its containing normalized library entry point, if any.
34-
*/
35-
export type EntryPointLookup = (filePath: string) => NormalizedEntryPoint | undefined;
36-
37-
/**
38-
* Creates an optimized, memoized lookup function that maps arbitrary file paths
39-
* to their closest containing library entry point.
40-
*
41-
* Entry point root directories are sorted in descending order of path length so that
42-
* more specific, nested sub-entry points take precedence over shallower or primary
43-
* entry points. Lookups are cached to avoid repeated path scanning.
44-
*
45-
* @example
46-
* Given two entry points:
47-
* - Primary entry point `.` at `/project/src/public-api.ts` (dir: `/project/src`)
48-
* - Secondary entry point `./testing` at `/project/src/testing/public-api.ts` (dir: `/project/src/testing`)
49-
*
50-
* ```ts
51-
* const findEntryPoint = createEntryDirectoryLookup(entryPoints);
52-
*
53-
* // Resolves to the 'testing' sub-entry point because /project/src/testing is the longest matching prefix:
54-
* findEntryPoint('/project/src/testing/test-bed.ts'); // -> NormalizedEntryPoint ('./testing')
55-
*
56-
* // Resolves to the primary entry point:
57-
* findEntryPoint('/project/src/button.ts'); // -> NormalizedEntryPoint ('.')
58-
*
59-
* // Returns undefined for files located outside any entry point directory:
60-
* findEntryPoint('/project/shared/utils.ts'); // -> undefined
61-
* ```
62-
*
63-
* @param entryPoints Iterable of normalized entry points.
64-
* @returns An {@link EntryPointLookup} function that returns the owning {@link NormalizedEntryPoint},
65-
* or `undefined` if the file does not belong to any entry point directory.
66-
*/
67-
export function createEntryDirectoryLookup(
68-
entryPoints: Iterable<NormalizedEntryPoint>,
69-
): EntryPointLookup {
70-
const dirs = Array.from(entryPoints, (ep) => {
71-
const dir = toPosixPath(path.dirname(ep.entryFilePath));
72-
73-
return {
74-
ep,
75-
dir,
76-
dirSlash: dir.endsWith('/') ? dir : `${dir}/`,
77-
};
78-
}).sort((a, b) => b.dir.length - a.dir.length);
79-
80-
const cache = new Map<string, NormalizedEntryPoint | undefined>();
81-
82-
return (filePath: string): NormalizedEntryPoint | undefined => {
83-
const posix = toPosixPath(filePath);
84-
const cached = cache.get(posix);
85-
if (cached !== undefined || cache.has(posix)) {
86-
return cached;
87-
}
88-
const found = dirs.find(({ dir, dirSlash }) => posix === dir || posix.startsWith(dirSlash))?.ep;
89-
cache.set(posix, found);
90-
91-
return found;
92-
};
93-
}
94-
9529
/**
9630
* Computes the base bundle file name for an entry point.
9731
*

0 commit comments

Comments
 (0)