Skip to content

Commit da7063f

Browse files
committed
refactor(@angular/build): provide a pre-link resolution condition for APF
To support future APF changes that may include pre-linked code specific to the Angular version used to create the package, an additional package resolution condition will now be automatically added to the build process for applications. A condition in the form of `angular:linked-<version>`, where `<version>` is the full package version of `@angular/core`, will now be present during application builds. This change in combination with APF changes will allow matching packages to avoid the linking step during a build. Non-version matching packages will continue to function and use the existing linking transformation process.
1 parent 4955ee0 commit da7063f

File tree

2 files changed

+30
-1
lines changed

2 files changed

+30
-1
lines changed

packages/angular/build/src/builders/application/options.ts

+21-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import type { BuilderContext } from '@angular-devkit/architect';
1010
import type { Plugin } from 'esbuild';
1111
import { realpathSync } from 'node:fs';
12-
import { access, constants } from 'node:fs/promises';
12+
import { access, constants, readFile } from 'node:fs/promises';
1313
import { createRequire } from 'node:module';
1414
import path from 'node:path';
1515
import { normalizeAssetPatterns, normalizeOptimization, normalizeSourceMaps } from '../../utils';
@@ -499,6 +499,7 @@ export async function normalizeOptions(
499499
templateUpdates: !!options.templateUpdates,
500500
incrementalResults: !!options.incrementalResults,
501501
customConditions: options.conditions,
502+
frameworkVersion: await findFrameworkVersion(projectRoot),
502503
};
503504
}
504505

@@ -706,3 +707,22 @@ function normalizeExternals(value: string[] | undefined): string[] | undefined {
706707

707708
return [...new Set(value.map((d) => (d.endsWith('/*') ? d.slice(0, -2) : d)))];
708709
}
710+
711+
async function findFrameworkVersion(projectRoot: string): Promise<string> {
712+
// Create a custom require function for ESM compliance.
713+
// NOTE: The trailing slash is significant.
714+
const projectResolve = createRequire(projectRoot + '/').resolve;
715+
716+
try {
717+
const manifestPath = projectResolve('@angular/core/package.json');
718+
const manifestData = await readFile(manifestPath, 'utf-8');
719+
const manifestObject = JSON.parse(manifestData) as { version: string };
720+
const version = manifestObject.version;
721+
722+
return version;
723+
} catch {
724+
throw new Error(
725+
'Error: It appears that "@angular/core" is missing as a dependency. Please ensure it is included in your project.',
726+
);
727+
}
728+
}

packages/angular/build/src/tools/esbuild/application-code-bundle.ts

+9
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu
547547
jsonLogs,
548548
i18nOptions,
549549
customConditions,
550+
frameworkVersion,
550551
} = options;
551552

552553
// Ensure unique hashes for i18n translation changes when using post-process inlining.
@@ -570,6 +571,14 @@ function getEsBuildCommonOptions(options: NormalizedApplicationBuildOptions): Bu
570571
'es2015',
571572
'es2020',
572573
];
574+
// The pre-linked code is not used with JIT for two reasons:
575+
// 1) The pre-linked code may not have the metadata included that is required for JIT
576+
// 2) The CLI is otherwise setup to use runtime linking for JIT to match the application template compilation
577+
if (!jit) {
578+
// The pre-linked package condition is based on the framework version.
579+
// Currently this is specific to each patch version of the framework.
580+
conditions.push('angular:linked-' + frameworkVersion);
581+
}
573582

574583
// Append custom conditions if present
575584
if (customConditions) {

0 commit comments

Comments
 (0)