Skip to content

Commit 3ba995e

Browse files
alan-agius4dherges
authored andcommitted
perf: reduce memory consumption (#1022)
Use a single file cache to reduce memory consumption when having multiple entrypoints. This also help to improve the build time due to after the analyse the files will be already cached.
1 parent 8e13149 commit 3ba995e

File tree

5 files changed

+56
-36
lines changed

5 files changed

+56
-36
lines changed

src/lib/ng-v5/entry-point/ts/compile-ngc.transform.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,28 @@ import * as path from 'path';
22
import * as ts from 'typescript';
33
import { Transform, transformFromPromise } from '../../../brocc/transform';
44
import { compileSourceFiles } from '../../../ngc/compile-source-files';
5-
import { TsConfig } from '../../../ts/tsconfig';
5+
import { TsConfig, setDependenciesTsConfigPaths } from '../../../ts/tsconfig';
66
import * as log from '../../../util/log';
7-
import { isEntryPointInProgress, EntryPointNode, isPackage } from '../../nodes';
7+
import { isEntryPointInProgress, EntryPointNode, isPackage, isEntryPoint } from '../../nodes';
88
import { StylesheetProcessor } from '../resources/stylesheet-processor';
99

1010
export const compileNgcTransform: Transform = transformFromPromise(async graph => {
1111
log.info(`Compiling TypeScript sources through ngc`);
1212
const entryPoint = graph.find(isEntryPointInProgress()) as EntryPointNode;
13-
const tsConfig: TsConfig = entryPoint.data.tsConfig;
13+
const entryPoints = graph.filter(isEntryPoint) as EntryPointNode[];
14+
// Add paths mappings for dependencies
15+
const tsConfig = setDependenciesTsConfigPaths(entryPoint.data.tsConfig, entryPoints);
1416

1517
// Compile TypeScript sources
1618
const { esm2015, esm5, declarations } = entryPoint.data.destinationFiles;
17-
const { compilationFileCache, moduleResolutionCache } = entryPoint.cache;
19+
const { sourcesFileCache, moduleResolutionCache } = entryPoint.cache;
1820
const { basePath, cssUrl, styleIncludePaths } = entryPoint.data.entryPoint;
1921
const stylesheetProcessor = new StylesheetProcessor(basePath, cssUrl, styleIncludePaths);
2022

2123
await Promise.all([
2224
compileSourceFiles(
2325
tsConfig,
24-
compilationFileCache,
26+
sourcesFileCache,
2527
moduleResolutionCache,
2628
stylesheetProcessor,
2729
{
@@ -32,7 +34,7 @@ export const compileNgcTransform: Transform = transformFromPromise(async graph =
3234
path.dirname(declarations)
3335
),
3436

35-
compileSourceFiles(tsConfig, compilationFileCache, moduleResolutionCache, stylesheetProcessor, {
37+
compileSourceFiles(tsConfig, sourcesFileCache, moduleResolutionCache, stylesheetProcessor, {
3638
outDir: path.dirname(esm5),
3739
target: ts.ScriptTarget.ES5,
3840
downlevelIteration: true,

src/lib/ng-v5/init/analyse-sources.transform.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import * as log from '../../util/log';
66
import { Transform } from '../../brocc/transform';
77
import { isEntryPoint, EntryPointNode } from '../nodes';
88
import { cacheCompilerHost } from '../../ts/cache-compiler-host';
9-
import { unique, flatten } from '../../util/array';
9+
import { unique } from '../../util/array';
10+
import { setDependenciesTsConfigPaths } from '../../ts/tsconfig';
1011

1112
export const analyseSourcesTransform: Transform = pipe(
1213
map(graph => {
@@ -26,14 +27,16 @@ export const analyseSourcesTransform: Transform = pipe(
2627
* @param entryPoints List of all entry points.
2728
*/
2829
function analyseEntryPoint(entryPoint: EntryPointNode, entryPoints: EntryPointNode[]) {
29-
const { tsConfig } = entryPoint.data;
30-
const { analysisFileCache, analysisModuleResolutionCache } = entryPoint.cache;
30+
const { sourcesFileCache, analysisModuleResolutionCache } = entryPoint.cache;
3131
const { moduleId } = entryPoint.data.entryPoint;
3232

3333
log.debug(`Analysing sources for ${moduleId}`);
3434

35+
// Add paths mappings for dependencies
36+
const tsConfig = setDependenciesTsConfigPaths(entryPoint.data.tsConfig, entryPoints, true);
37+
3538
const compilerHost = {
36-
...cacheCompilerHost(tsConfig.options, analysisFileCache, analysisModuleResolutionCache),
39+
...cacheCompilerHost(tsConfig.options, sourcesFileCache, analysisModuleResolutionCache),
3740
readResource: () => ''
3841
};
3942

src/lib/ng-v5/nodes.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,7 @@ export class EntryPointNode extends Node {
5858
readonly type = TYPE_NG_ENTRY_POINT;
5959

6060
cache = {
61-
analysisFileCache: new FileCache(),
62-
compilationFileCache: new FileCache(),
61+
sourcesFileCache: new FileCache(),
6362
moduleResolutionCache: ts.createModuleResolutionCache(process.cwd(), s => s),
6463
analysisModuleResolutionCache: ts.createModuleResolutionCache(process.cwd(), s => s)
6564
};

src/lib/ng-v5/package.transform.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ const watchTransformFactory = (
117117
let filePathsToClean: string[] = [filePath];
118118

119119
entryPoints.forEach((node: EntryPointNode) => {
120-
const { compilationFileCache } = node.cache;
121-
const cached = compilationFileCache.get(filePath);
120+
const { sourcesFileCache } = node.cache;
121+
const cached = sourcesFileCache.get(filePath);
122122

123123
// when a ts file changes we also need to clean it's .d.ts file
124124
// and the entrypoint metadata due to the fact that metadata is used to validate component properties
@@ -131,13 +131,12 @@ const watchTransformFactory = (
131131
filePathsToClean = unique(filePathsToClean);
132132

133133
entryPoints.forEach((node: EntryPointNode) => {
134-
const { analysisFileCache, compilationFileCache } = node.cache;
134+
const { sourcesFileCache } = node.cache;
135135

136136
let isDirty = false;
137137

138138
filePathsToClean.forEach(x => {
139-
isDirty = analysisFileCache.delete(x) || isDirty;
140-
isDirty = compilationFileCache.delete(x) || isDirty;
139+
isDirty = sourcesFileCache.delete(x) || isDirty;
141140
});
142141

143142
if (isDirty) {

src/lib/ts/tsconfig.ts

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -99,26 +99,43 @@ export const initializeTsConfig = (defaultTsConfig: TsConfig, entryPoints: Entry
9999
break;
100100
}
101101

102-
// Add paths mappings for dependencies
103-
const entryPointDeps = entryPoints.filter(x => x.data.entryPoint.moduleId !== entryPoint.moduleId);
104-
if (entryPointDeps.length > 0) {
105-
if (!tsConfig.options.paths) {
106-
tsConfig.options.paths = {};
107-
}
102+
currentEntryPoint.data.tsConfig = tsConfig;
103+
});
104+
};
108105

109-
for (let dep of entryPointDeps) {
110-
const { entryPoint, destinationFiles } = dep.data;
111-
const { moduleId, entryFilePath } = entryPoint;
112-
const mappedPath = [destinationFiles.declarations, entryFilePath];
106+
/**
107+
* Set the paths for entrypoint dependencies.
108+
*
109+
* This doesn't mutate the object.
110+
*
111+
* @param parsedTsConfig - A parsed tsconfig
112+
* @param entryPoints - A list of entryPoints
113+
* @param pointToSource Point the path mapping to either the source code or emitted declarations.
114+
* Typically for analysis one should point to the source files while for a compilation once should use the emitted declarations
115+
*/
116+
export function setDependenciesTsConfigPaths(
117+
parsedTsConfig: ng.ParsedConfiguration,
118+
entryPoints: EntryPointNode[],
119+
pointToSource = false
120+
) {
121+
const tsConfig = JSON.parse(JSON.stringify(parsedTsConfig));
113122

114-
if (!tsConfig.options.paths[moduleId]) {
115-
tsConfig.options.paths[moduleId] = mappedPath;
116-
} else {
117-
tsConfig.options.paths[moduleId].concat(mappedPath);
118-
}
119-
}
123+
// Add paths mappings for dependencies
124+
if (!tsConfig.options.paths) {
125+
tsConfig.options.paths = {};
126+
}
127+
128+
for (let dep of entryPoints) {
129+
const { entryPoint } = dep.data;
130+
const { moduleId, destinationFiles, entryFilePath } = entryPoint;
131+
const mappedPath = [pointToSource ? entryFilePath : destinationFiles.declarations];
132+
133+
if (!tsConfig.options.paths[moduleId]) {
134+
tsConfig.options.paths[moduleId] = mappedPath;
135+
} else {
136+
tsConfig.options.paths[moduleId].concat(mappedPath).reverse();
120137
}
138+
}
121139

122-
currentEntryPoint.data.tsConfig = tsConfig;
123-
});
124-
};
140+
return tsConfig;
141+
}

0 commit comments

Comments
 (0)