feat(ngcc): support invalidating the entry-point manifest (#35931)
In some scenarios it is useful for the developer to indicate to ngcc that it should not use the entry-point manifest file, and instead write a new one. In the ngcc command line tool, this option is set by specfying ``` --invalidate-entry-point-manifest ``` PR Close #35931
This commit is contained in:
parent
ec9f4d5bc6
commit
8ea61a19cd
|
@ -76,6 +76,13 @@ if (require.main === module) {
|
||||||
describe: 'The lowest severity logging message that should be output.',
|
describe: 'The lowest severity logging message that should be output.',
|
||||||
choices: ['debug', 'info', 'warn', 'error'],
|
choices: ['debug', 'info', 'warn', 'error'],
|
||||||
})
|
})
|
||||||
|
.option('invalidate-entry-point-manifest', {
|
||||||
|
describe:
|
||||||
|
'If this is set then ngcc will not read an entry-point manifest file from disk.\n' +
|
||||||
|
'Instead it will walk the directory tree as normal looking for entry-points, and then write a new manifest file.',
|
||||||
|
type: 'boolean',
|
||||||
|
default: false,
|
||||||
|
})
|
||||||
.strict()
|
.strict()
|
||||||
.help()
|
.help()
|
||||||
.parse(args);
|
.parse(args);
|
||||||
|
@ -95,6 +102,7 @@ if (require.main === module) {
|
||||||
const createNewEntryPointFormats = options['create-ivy-entry-points'];
|
const createNewEntryPointFormats = options['create-ivy-entry-points'];
|
||||||
const logLevel = options['l'] as keyof typeof LogLevel | undefined;
|
const logLevel = options['l'] as keyof typeof LogLevel | undefined;
|
||||||
const enableI18nLegacyMessageIdFormat = options['legacy-message-ids'];
|
const enableI18nLegacyMessageIdFormat = options['legacy-message-ids'];
|
||||||
|
const invalidateEntryPointManifest = options['invalidate-entry-point-manifest'];
|
||||||
|
|
||||||
(async() => {
|
(async() => {
|
||||||
try {
|
try {
|
||||||
|
@ -108,7 +116,7 @@ if (require.main === module) {
|
||||||
createNewEntryPointFormats,
|
createNewEntryPointFormats,
|
||||||
logger,
|
logger,
|
||||||
enableI18nLegacyMessageIdFormat,
|
enableI18nLegacyMessageIdFormat,
|
||||||
async: options['async'],
|
async: options['async'], invalidateEntryPointManifest,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (logger) {
|
if (logger) {
|
||||||
|
|
|
@ -39,7 +39,7 @@ import {hasBeenProcessed} from './packages/build_marker';
|
||||||
import {NgccConfiguration} from './packages/configuration';
|
import {NgccConfiguration} from './packages/configuration';
|
||||||
import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
|
import {EntryPoint, EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES, getEntryPointFormat} from './packages/entry_point';
|
||||||
import {makeEntryPointBundle} from './packages/entry_point_bundle';
|
import {makeEntryPointBundle} from './packages/entry_point_bundle';
|
||||||
import {EntryPointManifest} from './packages/entry_point_manifest';
|
import {EntryPointManifest, InvalidatingEntryPointManifest} from './packages/entry_point_manifest';
|
||||||
import {Transformer} from './packages/transformer';
|
import {Transformer} from './packages/transformer';
|
||||||
import {PathMappings} from './utils';
|
import {PathMappings} from './utils';
|
||||||
import {cleanOutdatedPackages} from './writing/cleaning/package_cleaner';
|
import {cleanOutdatedPackages} from './writing/cleaning/package_cleaner';
|
||||||
|
@ -117,6 +117,15 @@ export interface SyncNgccOptions {
|
||||||
* legacy message ids will all be stripped during translation.
|
* legacy message ids will all be stripped during translation.
|
||||||
*/
|
*/
|
||||||
enableI18nLegacyMessageIdFormat?: boolean;
|
enableI18nLegacyMessageIdFormat?: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to invalidate any entry-point manifest file that is on disk. Instead, walk the
|
||||||
|
* directory tree looking for entry-points, and then write a new entry-point manifest, if
|
||||||
|
* possible.
|
||||||
|
*
|
||||||
|
* Default: `false` (i.e. the manifest will be used if available)
|
||||||
|
*/
|
||||||
|
invalidateEntryPointManifest?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,11 +148,12 @@ export type NgccOptions = AsyncNgccOptions | SyncNgccOptions;
|
||||||
*/
|
*/
|
||||||
export function mainNgcc(options: AsyncNgccOptions): Promise<void>;
|
export function mainNgcc(options: AsyncNgccOptions): Promise<void>;
|
||||||
export function mainNgcc(options: SyncNgccOptions): void;
|
export function mainNgcc(options: SyncNgccOptions): void;
|
||||||
export function mainNgcc(
|
export function mainNgcc({basePath, targetEntryPointPath,
|
||||||
{basePath, targetEntryPointPath, propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES,
|
propertiesToConsider = SUPPORTED_FORMAT_PROPERTIES,
|
||||||
compileAllFormats = true, createNewEntryPointFormats = false,
|
compileAllFormats = true, createNewEntryPointFormats = false,
|
||||||
logger = new ConsoleLogger(LogLevel.info), pathMappings, async = false,
|
logger = new ConsoleLogger(LogLevel.info), pathMappings, async = false,
|
||||||
enableI18nLegacyMessageIdFormat = true}: NgccOptions): void|Promise<void> {
|
enableI18nLegacyMessageIdFormat = true,
|
||||||
|
invalidateEntryPointManifest = false}: NgccOptions): void|Promise<void> {
|
||||||
// Execute in parallel, if async execution is acceptable and there are more than 1 CPU cores.
|
// Execute in parallel, if async execution is acceptable and there are more than 1 CPU cores.
|
||||||
const inParallel = async && (os.cpus().length > 1);
|
const inParallel = async && (os.cpus().length > 1);
|
||||||
|
|
||||||
|
@ -154,7 +164,9 @@ export function mainNgcc(
|
||||||
const absBasePath = absoluteFrom(basePath);
|
const absBasePath = absoluteFrom(basePath);
|
||||||
const config = new NgccConfiguration(fileSystem, dirname(absBasePath));
|
const config = new NgccConfiguration(fileSystem, dirname(absBasePath));
|
||||||
const dependencyResolver = getDependencyResolver(fileSystem, logger, config, pathMappings);
|
const dependencyResolver = getDependencyResolver(fileSystem, logger, config, pathMappings);
|
||||||
const entryPointManifest = new EntryPointManifest(fileSystem, config, logger);
|
const entryPointManifest = invalidateEntryPointManifest ?
|
||||||
|
new InvalidatingEntryPointManifest(fileSystem, config, logger) :
|
||||||
|
new EntryPointManifest(fileSystem, config, logger);
|
||||||
|
|
||||||
// Bail out early if the work is already done.
|
// Bail out early if the work is already done.
|
||||||
const supportedPropertiesToConsider = ensureSupportedProperties(propertiesToConsider);
|
const supportedPropertiesToConsider = ensureSupportedProperties(propertiesToConsider);
|
||||||
|
|
|
@ -129,6 +129,18 @@ export class EntryPointManifest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A specialized implementation of the `EntryPointManifest` that can be used to invalidate the
|
||||||
|
* current manifest file.
|
||||||
|
*
|
||||||
|
* It always returns `null` from the `readEntryPointsUsingManifest()` method, which forces a new
|
||||||
|
* manifest to be created, which will overwrite the current file when `writeEntryPointManifest()` is
|
||||||
|
* called.
|
||||||
|
*/
|
||||||
|
export class InvalidatingEntryPointManifest extends EntryPointManifest {
|
||||||
|
readEntryPointsUsingManifest(basePath: AbsoluteFsPath): EntryPoint[]|null { return null; }
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The JSON format of the manifest file that is written to disk.
|
* The JSON format of the manifest file that is written to disk.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,22 +7,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/// <reference types="node" />
|
/// <reference types="node" />
|
||||||
|
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
|
|
||||||
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, join} from '../../../src/ngtsc/file_system';
|
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem, join} from '../../../src/ngtsc/file_system';
|
||||||
import {Folder, MockFileSystem, TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
import {Folder, MockFileSystem, TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||||||
import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers';
|
import {loadStandardTestFiles, loadTestFiles} from '../../../test/helpers';
|
||||||
import {getLockFilePath} from '../../src/locking/lock_file';
|
import {getLockFilePath} from '../../src/locking/lock_file';
|
||||||
import {mainNgcc} from '../../src/main';
|
import {mainNgcc} from '../../src/main';
|
||||||
import {markAsProcessed} from '../../src/packages/build_marker';
|
import {hasBeenProcessed, markAsProcessed} from '../../src/packages/build_marker';
|
||||||
import {EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES} from '../../src/packages/entry_point';
|
import {EntryPointJsonProperty, EntryPointPackageJson, SUPPORTED_FORMAT_PROPERTIES} from '../../src/packages/entry_point';
|
||||||
|
import {EntryPointManifestFile} from '../../src/packages/entry_point_manifest';
|
||||||
import {Transformer} from '../../src/packages/transformer';
|
import {Transformer} from '../../src/packages/transformer';
|
||||||
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
|
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
|
||||||
import {MockLogger} from '../helpers/mock_logger';
|
import {MockLogger} from '../helpers/mock_logger';
|
||||||
import {compileIntoApf, compileIntoFlatEs5Package} from './util';
|
import {compileIntoApf, compileIntoFlatEs5Package} from './util';
|
||||||
|
|
||||||
|
|
||||||
const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true});
|
const testFiles = loadStandardTestFiles({fakeCore: false, rxjs: true});
|
||||||
|
|
||||||
runInEachFileSystem(() => {
|
runInEachFileSystem(() => {
|
||||||
|
@ -982,6 +980,46 @@ runInEachFileSystem(() => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('with ignoreEntryPointManifest', () => {
|
||||||
|
it('should not read the entry-point manifest file', () => {
|
||||||
|
// Ensure there is a lock-file. Otherwise the manifest will not be written
|
||||||
|
fs.writeFile(_('/yarn.lock'), 'DUMMY YARN LOCK FILE');
|
||||||
|
// Populate the manifest file
|
||||||
|
mainNgcc(
|
||||||
|
{basePath: '/node_modules', propertiesToConsider: ['esm5'], logger: new MockLogger()});
|
||||||
|
// Check that common/testings ES5 was processed
|
||||||
|
let commonTesting =
|
||||||
|
JSON.parse(fs.readFile(_('/node_modules/@angular/common/testing/package.json')));
|
||||||
|
expect(hasBeenProcessed(commonTesting, 'esm5')).toBe(true);
|
||||||
|
expect(hasBeenProcessed(commonTesting, 'esm2015')).toBe(false);
|
||||||
|
// Modify the manifest to test that is has no effect
|
||||||
|
let manifest: EntryPointManifestFile =
|
||||||
|
JSON.parse(fs.readFile(_('/node_modules/__ngcc_entry_points__.json')));
|
||||||
|
manifest.entryPointPaths = manifest.entryPointPaths.filter(
|
||||||
|
paths => paths[1] !== _('/node_modules/@angular/common/testing'));
|
||||||
|
fs.writeFile(_('/node_modules/__ngcc_entry_points__.json'), JSON.stringify(manifest));
|
||||||
|
// Now run ngcc again ignoring this manifest but trying to process ES2015, which are not yet
|
||||||
|
// processed.
|
||||||
|
mainNgcc({
|
||||||
|
basePath: '/node_modules',
|
||||||
|
propertiesToConsider: ['esm2015'],
|
||||||
|
logger: new MockLogger(),
|
||||||
|
invalidateEntryPointManifest: true,
|
||||||
|
});
|
||||||
|
// Check that common/testing ES2015 is now processed, despite the manifest not listing it
|
||||||
|
commonTesting =
|
||||||
|
JSON.parse(fs.readFile(_('/node_modules/@angular/common/testing/package.json')));
|
||||||
|
expect(hasBeenProcessed(commonTesting, 'esm5')).toBe(true);
|
||||||
|
expect(hasBeenProcessed(commonTesting, 'esm2015')).toBe(true);
|
||||||
|
// Check that the newly computed manifest has written to disk, containing the path that we
|
||||||
|
// had removed earlier.
|
||||||
|
manifest = JSON.parse(fs.readFile(_('/node_modules/__ngcc_entry_points__.json')));
|
||||||
|
expect(manifest.entryPointPaths).toContain([
|
||||||
|
_('/node_modules/@angular/common'), _('/node_modules/@angular/common/testing')
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('diagnostics', () => {
|
describe('diagnostics', () => {
|
||||||
it('should fail with formatted diagnostics when an error diagnostic is produced', () => {
|
it('should fail with formatted diagnostics when an error diagnostic is produced', () => {
|
||||||
loadTestFiles([
|
loadTestFiles([
|
||||||
|
|
Loading…
Reference in New Issue