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

Commit

Permalink
fix(optimizations): comment out code instead of purge it so source-ma…
Browse files Browse the repository at this point in the history
…ps don't error out in some edge

comment out code instead of purge it so source-maps don't error out in some edge cases
  • Loading branch information
danbucholtz committed Feb 23, 2017
1 parent 627f5d4 commit 1dedc53
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 54 deletions.
7 changes: 5 additions & 2 deletions src/optimization/decorators.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('optimization', () => {
process.env = originalEnv;
});

it('should purge the decorators', () => {
it('should comment out the decorator statement', () => {
// arrange
const decoratorStatement = `
IonicModule.decorators = [
Expand Down Expand Up @@ -247,7 +247,10 @@ some more content

// assert
expect(result).not.toEqual(knownContent);
expect(result.indexOf(decoratorStatement)).toEqual(-1);
const regex = decorators.getDecoratorRegex();
const matches = regex.exec(result);
expect(matches).toBeTruthy();
expect(result.indexOf(`/*${matches[0]}*/`)).toBeGreaterThan(0);
expect(result.indexOf(additionalGeneratedContent)).toBeGreaterThan(-1);
});
});
Expand Down
10 changes: 8 additions & 2 deletions src/optimization/decorators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ export function purgeDecorators(filePath: string, fileContent: string) {
export function purgeIndexDecorator(filePath: string, fileContent: string) {
if (process.env[Constants.ENV_VAR_IONIC_ANGULAR_ENTRY_POINT] === filePath) {
Logger.debug(`Purging index file decorator for ${filePath}`);
return fileContent.replace(DECORATORS_REGEX, '');
const DECORATORS_REGEX = getDecoratorRegex();
const matches = DECORATORS_REGEX.exec(fileContent);
if (matches && matches.length) {
return fileContent.replace(matches[0], `/*${matches[0]}*/`);
}
}
return fileContent;
}

const DECORATORS_REGEX = /IonicModule.decorators.=[\s\S\n]*?([\s\S\n]*?)];/igm;
export function getDecoratorRegex() {
return /IonicModule.decorators.=[\s\S\n]*?([\s\S\n]*?)];/igm;
}
113 changes: 77 additions & 36 deletions src/optimization/treeshake.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { join } from 'path';
import { join, relative } from 'path';
import * as treeshake from './treeshake';
import * as Constants from '../util/constants';
import * as helpers from '../util/helpers';


let originalEnv: any = null;
Expand Down Expand Up @@ -1207,15 +1208,26 @@ export const AppModuleNgFactory = new import0.NgModuleFactory(AppModuleInjector,
const componentFactoryPath2 = `/Users/dan/Dev/myApp3/node_modules/ionic-angular/components/alert/alert-component.ngfactory.js`;

// act
let updatedContent = treeshake.purgeComponentNgFactoryImportAndUsage(appModuleNgFactoryPath, knownContent, componentFactoryPath);
updatedContent = treeshake.purgeComponentNgFactoryImportAndUsage(appModuleNgFactoryPath, updatedContent, componentFactoryPath2);
const updatedContent = treeshake.purgeComponentNgFactoryImportAndUsage(appModuleNgFactoryPath, knownContent, componentFactoryPath);
const updatedContentAgain = treeshake.purgeComponentNgFactoryImportAndUsage(appModuleNgFactoryPath, updatedContent, componentFactoryPath2);

// assert
expect(updatedContent).not.toEqual(knownContent);
expect(updatedContent.indexOf(knownImport)).toEqual(-1);
expect(updatedContent.indexOf(knownImport2)).toEqual(-1);
expect(updatedContent.indexOf(knownImportUsage)).toEqual(-1);
expect(updatedContent.indexOf(knownImportUsage2)).toEqual(-1);
expect(updatedContentAgain).not.toEqual(knownContent);
const knownImportOneRegex = treeshake.generateWildCardImportRegex('../../node_modules/ionic-angular/components/action-sheet/action-sheet-component.ngfactory');
const knownImportTwoRegex = treeshake.generateWildCardImportRegex('../../node_modules/ionic-angular/components/alert/alert-component.ngfactory');
const knownImportOneResults = knownImportOneRegex.exec(updatedContentAgain);
const knownImportTwoResults = knownImportTwoRegex.exec(updatedContentAgain);
const knownNamedImportOne = knownImportOneResults[1].trim();
const knownNamedImportTwo = knownImportTwoResults[1].trim();
expect(updatedContentAgain.indexOf(`/*${knownImportOneResults[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContentAgain.indexOf(`/*${knownImportTwoResults[0]}*/`)).toBeGreaterThanOrEqual(0);

const removeFromConstructorRegexOne = treeshake.generateRemoveComponentFromConstructorRegex(knownNamedImportOne);
const removeFromConstructorRegexTwo = treeshake.generateRemoveComponentFromConstructorRegex(knownNamedImportTwo);
const removeFromConstructorOneResults = removeFromConstructorRegexOne.exec(updatedContentAgain);
const removeFromConstructorTwoResults = removeFromConstructorRegexTwo.exec(updatedContentAgain);
expect(updatedContentAgain.indexOf(`/*${removeFromConstructorOneResults[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContentAgain.indexOf(`/*${removeFromConstructorTwoResults[0]}*/`)).toBeGreaterThanOrEqual(0);
});
});

Expand All @@ -1235,32 +1247,32 @@ export const AppModuleNgFactory = new import0.NgModuleFactory(AppModuleInjector,
// arrange

const ifStatementOne = `
if ((token === import32.ActionSheetController)) {
return this._ActionSheetController_54;
}
if ((token === import32.ActionSheetController)) {
return this._ActionSheetController_54;
}
`;
const ifStatementTwo = `
if ((token === import33.AlertController)) {
return this._AlertController_55;
}
if ((token === import33.AlertController)) {
return this._AlertController_55;
}
`;

const getterOne = `
get _ActionSheetController_54() {
if ((this.__ActionSheetController_54 == null)) {
(this.__ActionSheetController_54 = new import32.ActionSheetController(this._App_19, this._Config_16));
}
return this.__ActionSheetController_54;
}
get _ActionSheetController_54() {
if ((this.__ActionSheetController_54 == null)) {
(this.__ActionSheetController_54 = new import32.ActionSheetController(this._App_19, this._Config_16));
}
return this.__ActionSheetController_54;
}
`;

const getterTwo = `
get _AlertController_55() {
if ((this.__AlertController_55 == null)) {
(this.__AlertController_55 = new import33.AlertController(this._App_19, this._Config_16));
}
return this.__AlertController_55;
}
get _AlertController_55() {
if ((this.__AlertController_55 == null)) {
(this.__AlertController_55 = new import33.AlertController(this._App_19, this._Config_16));
}
return this.__AlertController_55;
}
`;

const knownContent = `
Expand Down Expand Up @@ -1916,22 +1928,47 @@ export const AppModuleNgFactory = new import0.NgModuleFactory(AppModuleInjector,
//# sourceMappingURL=app.module.ngfactory.js.map
`;

const nodeModulesPath = '/Users/dan/Dev/myApp3/node_modules';

const appModuleNgFactoryPath = `/Users/dan/Dev/myApp3/src/app/app.module.ngfactory.js`;
const controllerPath = `/Users/dan/Dev/myApp3/node_modules/ionic-angular/components/action-sheet/action-sheet-controller.js`;
const controllerPath2 = `/Users/dan/Dev/myApp3/node_modules/ionic-angular/components/alert/alert-controller.js`;
const controllerPath = join(nodeModulesPath, 'ionic-angular', 'components', 'action-sheet', 'action-sheet-controller.js');
const controllerPath2 = join(nodeModulesPath, 'ionic-angular', 'components', 'alert', 'alert-controller.js');

// act

let updatedContent = treeshake.purgeProviderControllerImportAndUsage(appModuleNgFactoryPath, knownContent, controllerPath);
updatedContent = treeshake.purgeProviderControllerImportAndUsage(appModuleNgFactoryPath, knownContent, controllerPath2);
updatedContent = treeshake.purgeProviderControllerImportAndUsage(appModuleNgFactoryPath, updatedContent, controllerPath2);

// assert
expect(updatedContent).not.toEqual(knownContent);
/*expect(updatedContent.indexOf(ifStatementOne)).toEqual(-1);
expect(updatedContent.indexOf(ifStatementTwo)).toEqual(-1);
expect(updatedContent.indexOf(getterOne)).toEqual(-1);
expect(updatedContent.indexOf(getterTwo)).toEqual(-1);
*/
const relativeImportPathOne = helpers.changeExtension(relative(nodeModulesPath, controllerPath), '');
const relativeImportPathTwo = helpers.changeExtension(relative(nodeModulesPath, controllerPath2), '');

const importRegexOne = treeshake.generateWildCardImportRegex(relativeImportPathOne);
const importRegexTwo = treeshake.generateWildCardImportRegex(relativeImportPathTwo);
const importResultOne = importRegexOne.exec(updatedContent);
const importResultTwo = importRegexTwo.exec(updatedContent);
expect(updatedContent.indexOf(`/*${importResultOne[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContent.indexOf(`/*${importResultTwo[0]}*/`)).toBeGreaterThanOrEqual(0);

const namedImportOne = importResultOne[1].trim();
const namedImportTwo = importResultTwo[1].trim();

const purgeGetterRegExOne = treeshake.generateRemoveGetterFromImportRegex(namedImportOne);
const purgeGetterResultsOne = purgeGetterRegExOne.exec(updatedContent);
const purgeIfRegExOne = treeshake.generateRemoveIfStatementRegex(namedImportOne);
const purgeIfResultsOne = purgeIfRegExOne.exec(updatedContent);

const purgeGetterRegExTwo = treeshake.generateRemoveGetterFromImportRegex(namedImportTwo);

const purgeGetterResultsTwo = purgeGetterRegExTwo.exec(updatedContent);
const purgeIfRegExTwo = treeshake.generateRemoveIfStatementRegex(namedImportTwo);
const purgeIfResultsTwo = purgeIfRegExTwo.exec(updatedContent);

expect(updatedContent.indexOf(`/*${purgeGetterResultsOne[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContent.indexOf(`/*${purgeIfResultsOne[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContent.indexOf(`/*${purgeGetterResultsTwo[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContent.indexOf(`/*${purgeIfResultsTwo[0]}*/`)).toBeGreaterThanOrEqual(0);
});
});

Expand Down Expand Up @@ -1999,8 +2036,12 @@ export const AppModuleNgFactory = new import0.NgModuleFactory(AppModuleInjector,

// assert
expect(updatedContent).not.toEqual(knownContent);
expect(updatedContent.indexOf(classOne)).toEqual(-1);
expect(updatedContent.indexOf(classTwo)).toEqual(-1);
const regexOne = treeshake.generateIonicModulePurgeProviderRegex(classOne);
const regexTwo = treeshake.generateIonicModulePurgeProviderRegex(classTwo);
const resultsOne = regexOne.exec(updatedContent);
const resultsTwo = regexTwo.exec(updatedContent);
expect(updatedContent.indexOf(`/*${resultsOne[0]}*/`)).toBeGreaterThanOrEqual(0);
expect(updatedContent.indexOf(`/*${resultsTwo[0]}*/`)).toBeGreaterThanOrEqual(0);
});
});
});
34 changes: 20 additions & 14 deletions src/optimization/treeshake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,14 @@ export function purgeUnusedImportsAndExportsFromIndex(indexFilePath: string, ind
// replace the import if it's found
let results: RegExpExecArray = null;
while ((results = importRegex.exec(indexFileContent)) && results.length) {
indexFileContent = indexFileContent.replace(importRegex, '');
indexFileContent = indexFileContent.replace(importRegex, `/*${results[0]}*/`);
}

results = null;
const exportRegex = generateExportRegex(importPath);
Logger.debug(`[treeshake] purgeUnusedImportsFromIndex: Removing exports with path ${importPath}`);
while ((results = exportRegex.exec(indexFileContent)) && results.length) {
indexFileContent = indexFileContent.replace(exportRegex, '');
indexFileContent = indexFileContent.replace(exportRegex, `/*${results[0]}*/`);
}
}

Expand All @@ -188,12 +188,12 @@ export function purgeUnusedImportsAndExportsFromIndex(indexFilePath: string, ind

function generateImportRegex(relativeImportPath: string) {
const cleansedString = escapeStringForRegex(relativeImportPath);
return new RegExp(`import.*?{(.+)}.*?from.*?'${cleansedString}';`);
return new RegExp(`^import.*?{(.+)}.*?from.*?['"\`]${cleansedString}['"\`];`, 'gm');
}

function generateExportRegex(relativeExportPath: string) {
const cleansedString = escapeStringForRegex(relativeExportPath);
return new RegExp(`export.*?{(.+)}.*?from.*?'${cleansedString}';`);
return new RegExp(`^export.*?{(.+)}.*?from.*?'${cleansedString}';`, 'gm');
}

export function purgeComponentNgFactoryImportAndUsage(appModuleNgFactoryPath: string, appModuleNgFactoryContent: string, componentFactoryPath: string) {
Expand All @@ -205,11 +205,14 @@ export function purgeComponentNgFactoryImportAndUsage(appModuleNgFactoryPath: st
const importRegex = generateWildCardImportRegex(importPath);
const results = importRegex.exec(appModuleNgFactoryContent);
if (results && results.length >= 2) {
appModuleNgFactoryContent = appModuleNgFactoryContent.replace(importRegex, '');
appModuleNgFactoryContent = appModuleNgFactoryContent.replace(importRegex, `/*${results[0]}*/`);
const namedImport = results[1].trim();
Logger.debug(`[treeshake] purgeComponentNgFactoryImportAndUsage: Purging code using named import ${namedImport}`);
const purgeFromConstructor = generateRemoveComponentFromConstructorRegex(namedImport);
appModuleNgFactoryContent = appModuleNgFactoryContent.replace(purgeFromConstructor, '');
const purgeFromConstructorResults = purgeFromConstructor.exec(appModuleNgFactoryContent);
if (purgeFromConstructorResults && purgeFromConstructorResults.length) {
appModuleNgFactoryContent = appModuleNgFactoryContent.replace(purgeFromConstructor, `/*${purgeFromConstructorResults[0]}*/`);
}
}
Logger.debug(`[treeshake] purgeComponentNgFactoryImportAndUsage: Starting to purge component ngFactory import/export ... DONE`);
return appModuleNgFactoryContent;
Expand All @@ -236,7 +239,7 @@ export function purgeProviderControllerImportAndUsage(appModuleNgFactoryPath: st
if (purgeGetterResults && purgeIfResults) {

Logger.debug(`[treeshake] purgeProviderControllerImportAndUsage: Purging imports ${namedImport}`);
appModuleNgFactoryContent = appModuleNgFactoryContent.replace(importRegex, '');
appModuleNgFactoryContent = appModuleNgFactoryContent.replace(importRegex, `/*${results[0]}*/`);

Logger.debug(`[treeshake] purgeProviderControllerImportAndUsage: Purging getter logic using ${namedImport}`);
const getterContentToReplace = purgeGetterResults[0];
Expand All @@ -257,29 +260,32 @@ export function purgeProviderControllerImportAndUsage(appModuleNgFactoryPath: st
export function purgeProviderClassNameFromIonicModuleForRoot(indexFileContent: string, providerClassName: string) {
Logger.debug(`[treeshake] purgeProviderClassNameFromIonicModuleForRoot: Purging reference in the ionicModule forRoot method ...`);
const regex = generateIonicModulePurgeProviderRegex(providerClassName);
indexFileContent = indexFileContent.replace(regex, '');
const results = regex.exec(indexFileContent);
if (results && results.length) {
indexFileContent = indexFileContent.replace(regex, `/*${results[0]}*/`);
}
Logger.debug(`[treeshake] purgeProviderClassNameFromIonicModuleForRoot: Purging reference in the ionicModule forRoot method ... DONE`);
return indexFileContent;
}

function generateWildCardImportRegex(relativeImportPath: string) {
export function generateWildCardImportRegex(relativeImportPath: string) {
const cleansedString = escapeStringForRegex(relativeImportPath);
return new RegExp(`import.*?as(.*?)from '${cleansedString}';`);
}

function generateRemoveComponentFromConstructorRegex(namedImport: string) {
export function generateRemoveComponentFromConstructorRegex(namedImport: string) {
return new RegExp(`${namedImport}\..*?,`);
}

export function generateRemoveGetterFromImportRegex(namedImport: string) {
const regexString = `(get _(.*?)_(\\d*)\\(\\) {([\\s\\S][^}]*?)${namedImport}([\\s\\S]*?)}([\\s\\S]*?)})`;
const regexString = `(get _.*?_\\d*\\(\\) {[\\s\\S][^}]*?${namedImport}[\\s\\S]*?}[\\s\\S]*?})`;
return new RegExp(regexString);
}

function generateRemoveIfStatementRegex(namedImport: string) {
export function generateRemoveIfStatementRegex(namedImport: string) {
return new RegExp(`if \\(\\(token === ${namedImport}.([\\S]*?)\\)\\) {([\\S\\s]*?)}`, `gm`);
}

function generateIonicModulePurgeProviderRegex(className: string) {
return new RegExp(`(^([\\s]*)${className},\\n)`, `m`);
export function generateIonicModulePurgeProviderRegex(className: string) {
return new RegExp(`${className},`, `gm`);
}

0 comments on commit 1dedc53

Please sign in to comment.