Skip to content
This repository was archived by the owner on May 1, 2020. It is now read-only.

Commit 0c81ce6

Browse files
authored
feature(providers): purge unused component providers
1 parent dbc9f31 commit 0c81ce6

File tree

10 files changed

+1810
-141
lines changed

10 files changed

+1810
-141
lines changed

src/optimization.spec.ts

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -6,67 +6,6 @@ import * as helpers from './util/helpers';
66
import { FileCache } from './util/file-cache';
77

88
describe('optimization task', () => {
9-
describe('processStatsImpl', () => {
10-
it('should convert object graph to known module map', () => {
11-
// arrange
12-
const moduleOne = '/Users/dan/myModuleOne.js';
13-
const moduleTwo = '/Users/dan/myModuleTwo.js';
14-
const moduleThree = '/Users/dan/myModuleThree.js';
15-
const moduleFour = '/Users/dan/myModuleFour.js';
16-
const objectGraph: any = {
17-
modules: [
18-
{
19-
identifier: moduleOne,
20-
reasons: [
21-
{
22-
moduleIdentifier: moduleTwo
23-
},
24-
{
25-
moduleIdentifier: moduleThree
26-
}
27-
]
28-
},
29-
{
30-
identifier: moduleTwo,
31-
reasons: [
32-
{
33-
moduleIdentifier: moduleThree
34-
}
35-
]
36-
},
37-
{
38-
identifier: moduleThree,
39-
reasons: [
40-
{
41-
moduleIdentifier: moduleOne
42-
}
43-
]
44-
},
45-
{
46-
identifier: moduleFour,
47-
reasons: []
48-
}
49-
]
50-
};
51-
// act
52-
const result = optimization.processStatsImpl(objectGraph);
53-
54-
// assert
55-
const setOne = result.get(moduleOne);
56-
expect(setOne.has(moduleTwo)).toBeTruthy();
57-
expect(setOne.has(moduleThree)).toBeTruthy();
58-
59-
const setTwo = result.get(moduleTwo);
60-
expect(setTwo.has(moduleThree)).toBeTruthy();
61-
62-
const setThree = result.get(moduleThree);
63-
expect(setThree.has(moduleOne)).toBeTruthy();
64-
65-
const setFour = result.get(moduleFour);
66-
expect(setFour.size).toEqual(0);
67-
});
68-
});
69-
709
describe('doOptimizations', () => {
7110
it('should not run optimizations unless flags are set', () => {
7211
// arrange

src/optimization.ts

Lines changed: 39 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { Logger } from './logger/logger';
33
import { fillConfigDefaults, getUserConfigFile, replacePathVars } from './util/config';
44
import * as Constants from './util/constants';
55
import { BuildError } from './util/errors';
6-
import { getBooleanPropertyValue } from './util/helpers';
6+
import { getBooleanPropertyValue, webpackStatsToDependencyMap, printDependencyMap } from './util/helpers';
77
import { BuildContext, TaskInfo } from './util/interfaces';
88
import { runWebpackFullBuild, WebpackConfig } from './webpack';
99
import { purgeDecorators } from './optimization/decorators';
10-
import { calculateUnusedComponents, purgeUnusedImportsAndExportsFromIndex } from './optimization/treeshake';
10+
import { getAppModuleNgFactoryPath, calculateUnusedComponents, purgeUnusedImportsAndExportsFromIndex, purgeComponentNgFactoryImportAndUsage, purgeProviderControllerImportAndUsage, purgeProviderClassNameFromIonicModuleForRoot } from './optimization/treeshake';
1111

1212
export function optimization(context: BuildContext, configFile: string) {
1313
const logger = new Logger(`optimization`);
@@ -24,7 +24,12 @@ export function optimization(context: BuildContext, configFile: string) {
2424
function optimizationWorker(context: BuildContext, configFile: string) {
2525
const webpackConfig = getConfig(context, configFile);
2626
return runWebpackFullBuild(webpackConfig).then((stats: any) => {
27-
const dependencyMap = processStats(context, stats);
27+
const dependencyMap = webpackStatsToDependencyMap(context, stats);
28+
if (getBooleanPropertyValue(Constants.ENV_PRINT_ORIGINAL_DEPENDENCY_TREE)) {
29+
Logger.debug('Original Dependency Map Start');
30+
printDependencyMap(dependencyMap);
31+
Logger.debug('Original Dependency Map End');
32+
}
2833
return doOptimizations(context, dependencyMap);
2934
});
3035
}
@@ -42,7 +47,11 @@ export function doOptimizations(context: BuildContext, dependencyMap: Map<string
4247
purgeUnusedImports(context, results.purgedModules);
4348
}
4449

45-
printDependencyMap(modifiedMap);
50+
if (getBooleanPropertyValue(Constants.ENV_PRINT_MODIFIED_DEPENDENCY_TREE)) {
51+
Logger.debug('Modified Dependency Map Start');
52+
printDependencyMap(modifiedMap);
53+
Logger.debug('Modified Dependency Map End');
54+
}
4655

4756
return modifiedMap;
4857
}
@@ -65,53 +74,39 @@ function purgeUnusedImports(context: BuildContext, purgeDependencyMap: Map<strin
6574

6675
const updatedFileContent = purgeUnusedImportsAndExportsFromIndex(indexFilePath, file.content, modulesToPurge);
6776
context.fileCache.set(indexFilePath, { path: indexFilePath, content: updatedFileContent });
68-
}
6977

70-
function processStats(context: BuildContext, stats: any) {
71-
const statsObj = stats.toJson({
72-
source: false,
73-
timings: false,
74-
version: false,
75-
errorDetails: false,
76-
chunks: false,
77-
chunkModules: false
78-
});
79-
return processStatsImpl(statsObj);
78+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_ACTION_SHEET_CONTROLLER_PATH], process.env[Constants.ENV_ACTION_SHEET_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_ACTION_SHEET_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_ACTION_SHEET_CONTROLLER_CLASSNAME]);
79+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_ALERT_CONTROLLER_PATH], process.env[Constants.ENV_ALERT_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_ALERT_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_ALERT_CONTROLLER_CLASSNAME]);
80+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_LOADING_CONTROLLER_PATH], process.env[Constants.ENV_LOADING_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_LOADING_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_LOADING_CONTROLLER_CLASSNAME]);
81+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_MODAL_CONTROLLER_PATH], process.env[Constants.ENV_MODAL_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_MODAL_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_MODAL_CONTROLLER_CLASSNAME]);
82+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_PICKER_CONTROLLER_PATH], process.env[Constants.ENV_PICKER_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_PICKER_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_PICKER_CONTROLLER_CLASSNAME]);
83+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_POPOVER_CONTROLLER_PATH], process.env[Constants.ENV_POPOVER_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_POPOVER_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_POPOVER_CONTROLLER_CLASSNAME]);
84+
attemptToPurgeUnusedProvider(context, purgeDependencyMap, process.env[Constants.ENV_TOAST_CONTROLLER_PATH], process.env[Constants.ENV_TOAST_VIEW_CONTROLLER_PATH], process.env[Constants.ENV_TOAST_COMPONENT_FACTORY_PATH], process.env[Constants.ENV_TOAST_CONTROLLER_CLASSNAME]);
8085
}
8186

82-
export function processStatsImpl(webpackStats: WebpackStats) {
83-
const dependencyMap = new Map<string, Set<string>>();
84-
if (webpackStats && webpackStats.modules) {
85-
webpackStats.modules.forEach(webpackModule => {
86-
const moduleId = purgeWebpackPrefixFromPath(webpackModule.identifier);
87-
const dependencySet = new Set<string>();
88-
webpackModule.reasons.forEach(webpackDependency => {
89-
const depId = purgeWebpackPrefixFromPath(webpackDependency.moduleIdentifier);
90-
dependencySet.add(depId);
91-
});
92-
dependencyMap.set(moduleId, dependencySet);
93-
});
94-
}
87+
function attemptToPurgeUnusedProvider(context: BuildContext, dependencyMap: Map<string, Set<string>>, providerPath: string, providerComponentPath: string, providerComponentFactoryPath: string, providerClassName: string) {
88+
if (dependencyMap.has(providerPath)) {
89+
// awwww yissssssss
9590

96-
if (getBooleanPropertyValue(Constants.ENV_PRINT_DEPENDENCY_TREE)) {
97-
printDependencyMap(dependencyMap);
98-
}
91+
// first, get the content of the app module ngfactory file
92+
const appModuleNgFactoryPath = getAppModuleNgFactoryPath();
93+
const file = context.fileCache.get(appModuleNgFactoryPath);
94+
if (!file) {
95+
return;
96+
}
9997

100-
return dependencyMap;
101-
}
98+
let updatedContent = purgeComponentNgFactoryImportAndUsage(file.path, file.content, providerComponentFactoryPath);
99+
updatedContent = purgeProviderControllerImportAndUsage(file.path, updatedContent, providerPath);
100+
context.fileCache.set(appModuleNgFactoryPath, { path: appModuleNgFactoryPath, content: updatedContent});
102101

103-
export function purgeWebpackPrefixFromPath(filePath: string) {
104-
return filePath.replace(process.env[Constants.ENV_OPTIMIZATION_LOADER], '').replace(process.env[Constants.ENV_WEBPACK_LOADER], '').replace('!', '');
105-
}
102+
// purge the provider name from the forRoot method providers list
103+
const indexFilePath = process.env[Constants.ENV_VAR_IONIC_ANGULAR_ENTRY_POINT];
104+
const ionicIndexFile = context.fileCache.get(indexFilePath);
105+
let newIndexFileContent = purgeProviderClassNameFromIonicModuleForRoot(ionicIndexFile.content, providerClassName);
106106

107-
function printDependencyMap(map: Map<string, Set<string>>) {
108-
map.forEach((dependencySet: Set<string>, filePath: string) => {
109-
Logger.unformattedDebug('\n\n');
110-
Logger.unformattedDebug(`${filePath} is imported by the following files:`);
111-
dependencySet.forEach((importeePath: string) => {
112-
Logger.unformattedDebug(` ${importeePath}`);
113-
});
114-
});
107+
// purge the component from the index file
108+
context.fileCache.set(indexFilePath, { path: indexFilePath, content: newIndexFileContent});
109+
}
115110
}
116111

117112
export function getConfig(context: BuildContext, configFile: string): WebpackConfig {
@@ -132,15 +127,4 @@ const taskInfo: TaskInfo = {
132127
defaultConfigFile: 'optimization.config'
133128
};
134129

135-
export interface WebpackStats {
136-
modules: WebpackModule[];
137-
};
138130

139-
export interface WebpackModule {
140-
identifier: string;
141-
reasons: WebpackDependency[];
142-
};
143-
144-
export interface WebpackDependency {
145-
moduleIdentifier: string;
146-
};

0 commit comments

Comments
 (0)