Some tools (such as Language Server and ng-packagr) only care about the processed typings generated by ngcc. Forcing these tools to process the JavaScript files as well has two disadvantages: First, unnecessary work is being done, which is time consuming. But more importantly, it is not always possible to know how the final bundling tools will want the processed JavaScript to be configured. For example, the CLI would prefer the `--create-ivy-entry-points` option but this would break non-CLI build tooling. This commit adds a new option (`--typings-only` on the command line, and `typingsOnly` via programmatic API) that instructs ngcc to only render changes to the typings files for the entry-points that it finds, and not to write any JavaScript files. In order to process the typings, a JavaScript format will need to be analysed, but it will not be rendered to disk. When using this option, it is best to offer ngcc a wide range of possible JavaScript formats to choose from, and it will use the first format that it finds. Ideally you would configure it to try the `ES2015` FESM format first, since this will be the most performant. Fixes #40969 PR Close #40976
121 lines
4.8 KiB
TypeScript
121 lines
4.8 KiB
TypeScript
/**
|
|
* @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 * as ts from 'typescript';
|
|
|
|
import {absoluteFrom, AbsoluteFsPath, getFileSystem, NgtscCompilerHost} from '../../../src/ngtsc/file_system';
|
|
import {TestFile} from '../../../src/ngtsc/file_system/testing';
|
|
import {DtsProcessing} from '../../src/execution/tasks/api';
|
|
import {BundleProgram, makeBundleProgram} from '../../src/packages/bundle_program';
|
|
import {NgccEntryPointConfig} from '../../src/packages/configuration';
|
|
import {EntryPoint, EntryPointFormat} from '../../src/packages/entry_point';
|
|
import {EntryPointBundle} from '../../src/packages/entry_point_bundle';
|
|
import {NgccSourcesCompilerHost} from '../../src/packages/ngcc_compiler_host';
|
|
import {createModuleResolutionCache, EntryPointFileCache, SharedFileCache} from '../../src/packages/source_file_cache';
|
|
|
|
export type TestConfig = Pick<NgccEntryPointConfig, 'generateDeepReexports'>;
|
|
|
|
export function makeTestEntryPoint(
|
|
entryPointName: string, packageName: string = entryPointName, config?: TestConfig): EntryPoint {
|
|
return {
|
|
name: entryPointName,
|
|
path: absoluteFrom(`/node_modules/${entryPointName}`),
|
|
packageName,
|
|
packagePath: absoluteFrom(`/node_modules/${packageName}`),
|
|
packageJson: {name: entryPointName},
|
|
typings: absoluteFrom(`/node_modules/${entryPointName}/index.d.ts`),
|
|
compiledByAngular: true,
|
|
ignoreMissingDependencies: false,
|
|
generateDeepReexports: config !== undefined ? !!config.generateDeepReexports : false,
|
|
};
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @param format The format of the bundle.
|
|
* @param files The source files to include in the bundle.
|
|
* @param dtsFiles The typings files to include the bundle.
|
|
*/
|
|
export function makeTestEntryPointBundle(
|
|
packageName: string, format: EntryPointFormat, isCore: boolean, srcRootNames: AbsoluteFsPath[],
|
|
dtsRootNames?: AbsoluteFsPath[], config?: TestConfig,
|
|
enableI18nLegacyMessageIdFormat = false): EntryPointBundle {
|
|
const entryPoint = makeTestEntryPoint(packageName, packageName, config);
|
|
const src = makeTestBundleProgram(srcRootNames[0], isCore);
|
|
const dts = dtsRootNames ?
|
|
makeTestDtsBundleProgram(dtsRootNames[0], entryPoint.packagePath, isCore) :
|
|
null;
|
|
const isFlatCore = isCore && src.r3SymbolsFile === null;
|
|
return {
|
|
entryPoint,
|
|
format,
|
|
rootDirs: [absoluteFrom('/')],
|
|
src,
|
|
dts,
|
|
dtsProcessing: dtsRootNames ? DtsProcessing.Yes : DtsProcessing.No,
|
|
isCore,
|
|
isFlatCore,
|
|
enableI18nLegacyMessageIdFormat
|
|
};
|
|
}
|
|
|
|
export function makeTestBundleProgram(
|
|
path: AbsoluteFsPath, isCore: boolean = false,
|
|
additionalFiles?: AbsoluteFsPath[]): BundleProgram {
|
|
const fs = getFileSystem();
|
|
const entryPointPath = fs.dirname(path);
|
|
const rootDir = fs.dirname(entryPointPath);
|
|
const options: ts.CompilerOptions =
|
|
{allowJs: true, maxNodeModuleJsDepth: Infinity, checkJs: false, rootDir, rootDirs: [rootDir]};
|
|
const moduleResolutionCache = createModuleResolutionCache(fs);
|
|
const entryPointFileCache = new EntryPointFileCache(fs, new SharedFileCache(fs));
|
|
const host =
|
|
new NgccSourcesCompilerHost(fs, options, entryPointFileCache, moduleResolutionCache, rootDir);
|
|
return makeBundleProgram(
|
|
fs, isCore, rootDir, path, 'r3_symbols.js', options, host, additionalFiles);
|
|
}
|
|
|
|
export function makeTestDtsBundleProgram(
|
|
path: AbsoluteFsPath, packagePath: AbsoluteFsPath, isCore: boolean = false): BundleProgram {
|
|
const fs = getFileSystem();
|
|
const options = {};
|
|
const host = new NgtscCompilerHost(fs, options);
|
|
return makeBundleProgram(fs, isCore, packagePath, path, 'r3_symbols.d.ts', options, host);
|
|
}
|
|
|
|
export function convertToDirectTsLibImport(filesystem: TestFile[]) {
|
|
return filesystem.map(file => {
|
|
const contents =
|
|
file.contents
|
|
.replace(
|
|
`import * as tslib_1 from 'tslib';`,
|
|
`import { __decorate, __metadata, __read, __values, __param, __extends, __assign } from 'tslib';`)
|
|
.replace(/tslib_1\./g, '');
|
|
return {...file, contents};
|
|
});
|
|
}
|
|
|
|
export function convertToInlineTsLib(filesystem: TestFile[], suffix: string = '') {
|
|
return filesystem.map(file => {
|
|
const contents = file.contents
|
|
.replace(`import * as tslib_1 from 'tslib';`, `
|
|
var __decorate${suffix} = null;
|
|
var __metadata${suffix} = null;
|
|
var __read${suffix} = null;
|
|
var __values${suffix} = null;
|
|
var __param${suffix} = null;
|
|
var __extends${suffix} = null;
|
|
var __assign${suffix} = null;
|
|
`).replace(/tslib_1\.([_a-z]+)/gi, '$1' + suffix.replace('$', '$$'));
|
|
return {...file, contents};
|
|
});
|
|
}
|
|
|
|
export function getRootFiles(testFiles: TestFile[]): AbsoluteFsPath[] {
|
|
return testFiles.filter(f => f.isRoot !== false).map(f => absoluteFrom(f.name));
|
|
}
|