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

Commit 1f0de4a

Browse files
committed
refactor(optimizations): transpile down to es5 as part of bundling because transpiling after we apply optimizations results in uglify annotations being purged
1 parent be8e726 commit 1f0de4a

18 files changed

+120
-118
lines changed

config/webpack.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ module.exports = {
2626
{
2727
test: /\.ts$/,
2828
loader: process.env.IONIC_WEBPACK_LOADER
29+
},
30+
{
31+
test: /\.js$/,
32+
loader: process.env.IONIC_WEBPACK_TRANSPILE_LOADER
2933
}
3034
]
3135
},

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"tiny-lr": "1.0.3",
5757
"tslint": "3.15.1",
5858
"tslint-eslint-rules": "1.5.0",
59-
"uglify-js": "2.8.16",
59+
"uglify-js": "2.8.21",
6060
"webpack": "2.2.1",
6161
"ws": "1.1.1",
6262
"xml2js": "^0.4.17"
@@ -83,7 +83,7 @@
8383
"@types/node": "^7.0.4",
8484
"@types/node-sass": "^3.10.32",
8585
"@types/rewire": "^2.5.27",
86-
"@types/uglify-js": "^2.0.27",
86+
"@types/uglify-js": "^2.6.28",
8787
"@types/webpack": "^1.12.35",
8888
"@types/ws": "^0.0.38",
8989
"conventional-changelog-cli": "1.2.0",

src/minify.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { babili } from './babili';
55
import { cleancss } from './cleancss';
66
import { closure, isClosureSupported } from './closure';
77
import { Logger } from './logger/logger';
8-
import { transpileBundle } from './transpile';
98
import { uglifyjs } from './uglifyjs';
109

1110

@@ -48,10 +47,7 @@ export function minifyJs(context: BuildContext): Promise<void> {
4847

4948
function runUglify(context: BuildContext) {
5049
// uglify cannot handle ES2015, so convert it to ES5 before minifying (if needed)
51-
const promise = getBooleanPropertyValue(Constants.ENV_BUILD_TO_ES5) === true ? transpileBundle(context) : Promise.resolve();
52-
return promise.then(() => {
53-
return uglifyjs(context);
54-
});
50+
return uglifyjs(context);
5551
}
5652

5753
export function minifyCss(context: BuildContext) {

src/optimization.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,10 @@ function removeDecorators(context: BuildContext) {
8282
const jsFiles = context.fileCache.getAll().filter(file => extname(file.path) === '.js');
8383
jsFiles.forEach(jsFile => {
8484
let magicString = new MagicString(jsFile.content);
85-
magicString = purgeStaticFieldDecorators(jsFile.path, jsFile.content, getStringPropertyValue(Constants.ENV_VAR_IONIC_ANGULAR_DIR), getStringPropertyValue(Constants.ENV_VAR_AT_ANGULAR_DIR), context.srcDir, magicString);
86-
magicString = purgeStaticCtorFields(jsFile.path, jsFile.content, getStringPropertyValue(Constants.ENV_VAR_IONIC_ANGULAR_DIR), getStringPropertyValue(Constants.ENV_VAR_AT_ANGULAR_DIR), context.srcDir, magicString);
87-
magicString = purgeTranspiledDecorators(jsFile.path, jsFile.content, getStringPropertyValue(Constants.ENV_VAR_IONIC_ANGULAR_DIR), getStringPropertyValue(Constants.ENV_VAR_AT_ANGULAR_DIR), context.srcDir, magicString);
88-
magicString = addPureAnnotation(jsFile.path, jsFile.content, getStringPropertyValue(Constants.ENV_VAR_IONIC_ANGULAR_DIR), getStringPropertyValue(Constants.ENV_VAR_AT_ANGULAR_DIR), context.srcDir, magicString);
85+
magicString = purgeStaticFieldDecorators(jsFile.path, jsFile.content, magicString);
86+
magicString = purgeStaticCtorFields(jsFile.path, jsFile.content, magicString);
87+
magicString = purgeTranspiledDecorators(jsFile.path, jsFile.content, magicString);
88+
magicString = addPureAnnotation(jsFile.path, jsFile.content, magicString);
8989
jsFile.content = magicString.toString();
9090
const sourceMap = magicString.generateMap({
9191
source: basename(jsFile.path),

src/optimization/decorators.spec.ts

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { join } from 'path';
2-
import * as decorators from './decorators';
32

43
import * as MagicString from 'magic-string';
54

5+
import * as decorators from './decorators';
6+
import * as helpers from '../util/helpers';
7+
68
const baseDir = join(process.cwd(), 'myApp');
79
const ionicAngular = join(baseDir, 'node_modules', 'ionic-angular');
8-
const angularDir = join(baseDir, 'node_modules', '@angular');
9-
const srcDir = join(baseDir, 'src');
1010

1111

1212
describe('optimization', () => {
@@ -243,7 +243,8 @@ some more content
243243
// act
244244
let magicString = new MagicString(knownContent);
245245
const entryPoint = join(ionicAngular, 'index.js');
246-
magicString = decorators.purgeStaticFieldDecorators(entryPoint, knownContent, ionicAngular, angularDir, srcDir, magicString);
246+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
247+
magicString = decorators.purgeStaticFieldDecorators(entryPoint, knownContent, magicString);
247248
const result = magicString.toString();
248249

249250
// assert
@@ -288,7 +289,8 @@ ActionSheetController.ctorParameters = function () { return [
288289

289290
let magicString = new MagicString(knownContent);
290291
const entryPoint = join(ionicAngular, 'index.js');
291-
magicString = decorators.purgeStaticFieldDecorators(entryPoint, knownContent, ionicAngular, angularDir, srcDir, magicString);
292+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
293+
magicString = decorators.purgeStaticFieldDecorators(entryPoint, knownContent, magicString);
292294
const result = magicString.toString();
293295
expect(result).toEqual(knownContent);
294296
});
@@ -777,7 +779,8 @@ export function provideLocationStrategy(platformLocationStrategy, baseHref, conf
777779
`;
778780
let magicString = new MagicString(knownContent);
779781
const entryPoint = join(ionicAngular, 'index.js');
780-
magicString = decorators.purgeStaticFieldDecorators(entryPoint, knownContent, ionicAngular, angularDir, srcDir, magicString);
782+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
783+
magicString = decorators.purgeStaticFieldDecorators(entryPoint, knownContent, magicString);
781784
const result = magicString.toString();
782785
expect(result.indexOf(ionicModuleDecorator)).toEqual(-1);
783786
});
@@ -993,7 +996,8 @@ let actionSheetIds = -1;
993996

994997
let magicString = new MagicString(knownContent);
995998
const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js');
996-
magicString = decorators.purgeStaticFieldDecorators(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
999+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
1000+
magicString = decorators.purgeStaticFieldDecorators(filePath, knownContent, magicString);
9971001
const result = magicString.toString();
9981002
expect(result.indexOf(decoratorContent)).toEqual(-1);
9991003
expect(result.indexOf(propDecorators)).toEqual(-1);
@@ -1100,7 +1104,8 @@ var _a, _b, _c;
11001104

11011105
let magicString = new MagicString(knownContent);
11021106
const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js');
1103-
magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1107+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
1108+
magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, magicString);
11041109
const result: string = magicString.toString();
11051110
expect(result.indexOf(inputDecorator)).toEqual(-1);
11061111
expect(result.indexOf(outputDecorator)).toEqual(-1);
@@ -1275,7 +1280,8 @@ var _a, _b;
12751280

12761281
let magicString = new MagicString(knownContent);
12771282
const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js');
1278-
magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1283+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
1284+
magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, magicString);
12791285
const result: string = magicString.toString();
12801286
expect(result.indexOf(injectableDecorator)).toBeGreaterThan(1);
12811287
});
@@ -1326,7 +1332,8 @@ export { DashPage };
13261332

13271333
let magicString = new MagicString(knownContent);
13281334
const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js');
1329-
magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1335+
spyOn(helpers, helpers.isSrcOrIonicOrIonicDeps.name).and.returnValue(true);
1336+
magicString = decorators.purgeTranspiledDecorators(filePath, knownContent, magicString);
13301337
const result: string = magicString.toString();
13311338
expect(result.indexOf(selectDecorator)).toBeGreaterThan(1);
13321339
});
@@ -1402,7 +1409,7 @@ var _a, _b, _c;
14021409

14031410
let magicString = new MagicString(knownContent);
14041411
const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js');
1405-
magicString = decorators.addPureAnnotation(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1412+
magicString = decorators.addPureAnnotation(filePath, knownContent, magicString);
14061413
const result: string = magicString.toString();
14071414
expect(result).toEqual(expectedContent);
14081415
});
@@ -1510,7 +1517,7 @@ function CardContent_tsickle_Closure_declarations() {
15101517

15111518
let magicString = new MagicString(knownContent);
15121519
const filePath = join(ionicAngular, 'components', 'action-sheet', 'action-sheet-component.js');
1513-
magicString = decorators.addPureAnnotation(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1520+
magicString = decorators.addPureAnnotation(filePath, knownContent, magicString);
15141521
const result: string = magicString.toString();
15151522
expect(result).toEqual(expectedContent);
15161523
});
@@ -1570,7 +1577,8 @@ function Badge_tsickle_Closure_declarations() {
15701577

15711578
let magicString = new MagicString(knownContent);
15721579
const filePath = join(ionicAngular, 'components', 'badge', 'badge.js');
1573-
magicString = decorators.purgeStaticCtorFields(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1580+
spyOn(helpers, helpers.isIonicOrAngular.name).and.returnValue(true);
1581+
magicString = decorators.purgeStaticCtorFields(filePath, knownContent, magicString);
15741582
const result: string = magicString.toString();
15751583
expect(result.indexOf(ctorParams)).toEqual(-1);
15761584
});
@@ -1604,7 +1612,8 @@ function Avatar_tsickle_Closure_declarations() {
16041612

16051613
let magicString = new MagicString(knownContent);
16061614
const filePath = join(ionicAngular, 'components', 'badge', 'badge.js');
1607-
magicString = decorators.purgeStaticCtorFields(filePath, knownContent, ionicAngular, angularDir, srcDir, magicString);
1615+
spyOn(helpers, helpers.isIonicOrAngular.name).and.returnValue(true);
1616+
magicString = decorators.purgeStaticCtorFields(filePath, knownContent, magicString);
16081617
const result: string = magicString.toString();
16091618
expect(result.indexOf(ctorParams)).toEqual(-1);
16101619
});

src/optimization/decorators.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ import {
1414

1515
import { Logger } from '../logger/logger';
1616
import * as Constants from '../util/constants';
17-
import { getStringPropertyValue } from '../util/helpers';
17+
import { getStringPropertyValue, isIonicOrAngular, isSrcOrIonicOrIonicDeps } from '../util/helpers';
1818
import { MagicString } from '../util/interfaces';
19-
import { getNodeStringContent, findNodes, getTypescriptSourceFile } from '../util/typescript-utils';
19+
import { findNodes, getTypescriptSourceFile } from '../util/typescript-utils';
2020

21-
export function addPureAnnotation(filePath: string, originalFileContent: string, ionicAngularDir: string, angularDir: string, srcDir: string, magicString: MagicString) {
21+
export function addPureAnnotation(filePath: string, originalFileContent: string, magicString: MagicString) {
2222
Logger.debug(`[decorators] addPureAnnotation: processing ${filePath} ...`);
2323
const typescriptFile = getTypescriptSourceFile(filePath, originalFileContent);
2424
const parenthesizedExpressions = findNodes(typescriptFile, typescriptFile, SyntaxKind.ParenthesizedExpression, false) as ParenthesizedExpression[];
@@ -48,8 +48,8 @@ export function addPureAnnotation(filePath: string, originalFileContent: string,
4848
return magicString;
4949
}
5050

51-
export function purgeTranspiledDecorators(filePath: string, originalFileContent: string, ionicAngularDir: string, angularDir: string, srcDir: string, magicString: MagicString) {
52-
if (filePath.indexOf(angularDir) >= 0 || filePath.indexOf(ionicAngularDir) >= 0 || filePath.indexOf(srcDir) >= 0) {
51+
export function purgeTranspiledDecorators(filePath: string, originalFileContent: string, magicString: MagicString) {
52+
if (isSrcOrIonicOrIonicDeps(filePath)) {
5353
Logger.debug(`[decorators] purgeTranspiledDecorators: processing ${filePath} ...`);
5454
const typescriptFile = getTypescriptSourceFile(filePath, originalFileContent);
5555
const expressionsToRemove = getTranspiledDecoratorExpressionStatements(typescriptFile);
@@ -114,8 +114,8 @@ function getTranspiledDecoratorExpressionStatements(sourceFile: SourceFile) {
114114
return toReturn;
115115
}
116116

117-
export function purgeStaticFieldDecorators(filePath: string, originalFileContent: string, ionicAngularDir: string, angularDir: string, srcDir: string, magicString: MagicString) {
118-
if (filePath.indexOf(angularDir) >= 0 || filePath.indexOf(ionicAngularDir) >= 0 || filePath.indexOf(srcDir) >= 0) {
117+
export function purgeStaticFieldDecorators(filePath: string, originalFileContent: string, magicString: MagicString) {
118+
if (isSrcOrIonicOrIonicDeps(filePath)) {
119119
Logger.debug(`[decorators] purgeStaticFieldDecorators: processing ${filePath} ...`);
120120
const typescriptFile = getTypescriptSourceFile(filePath, originalFileContent);
121121

@@ -130,10 +130,10 @@ export function purgeStaticFieldDecorators(filePath: string, originalFileContent
130130
return magicString;
131131
}
132132

133-
export function purgeStaticCtorFields(filePath: string, originalFileContent: string, ionicAngularDir: string, angularDir: string, srcDir: string, magicString: MagicString) {
133+
export function purgeStaticCtorFields(filePath: string, originalFileContent: string, magicString: MagicString) {
134134
// TODO - we could extend this to other libs and stuff too such as material 2, but that doesn't seem
135135
// particularly maintainable
136-
if ((filePath.indexOf(angularDir) >= 0 || filePath.indexOf(ionicAngularDir) >= 0) && !isIonicEntryComponent(filePath)) {
136+
if (isIonicOrAngular(filePath) && !isIonicEntryComponent(filePath)) {
137137
Logger.debug(`[decorators] purgeStaticCtorFields: processing ${filePath} ...`);
138138
const typescriptFile = getTypescriptSourceFile(filePath, originalFileContent);
139139
const expressionStatements = findNodes(typescriptFile, typescriptFile, SyntaxKind.ExpressionStatement, false) as ExpressionStatement[];

src/transpile.ts

Lines changed: 2 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -300,40 +300,6 @@ function writeTranspiledFilesCallback(fileCache: FileCache, sourcePath: string,
300300
}
301301
}
302302

303-
export function transpileBundle(context: BuildContext, target: ts.ScriptTarget = ts.ScriptTarget.ES5) {
304-
return Promise.resolve()
305-
.then(() => {
306-
return transpileBundleImpl(context, target);
307-
});
308-
}
309-
310-
function transpileBundleImpl(context: BuildContext, target: ts.ScriptTarget) {
311-
const logger = new Logger('transpile bundle');
312-
try {
313-
const files = readdirSync(context.buildDir);
314-
files.forEach((file) => {
315-
if (path.extname(file) === '.js' && file.indexOf('polyfills') === -1 && file.indexOf('sw-toolbox') === -1) {
316-
const bundlePath = path.join(context.buildDir, file);
317-
const bundleContent = readFileSync(bundlePath).toString();
318-
const tsConfig = getTsConfig(context);
319-
const transpileOptions: ts.TranspileOptions = {
320-
compilerOptions: tsConfig.options,
321-
fileName: bundlePath,
322-
reportDiagnostics: true
323-
};
324-
// override the target value
325-
transpileOptions.compilerOptions.target = target;
326-
const transpiledOutput = ts.transpileModule(bundleContent, transpileOptions);
327-
writeFileSync(bundlePath, transpiledOutput.outputText);
328-
}
329-
});
330-
logger.finish();
331-
} catch (ex) {
332-
throw logger.fail(ex);
333-
}
334-
}
335-
336-
337303
export function getTsConfig(context: BuildContext, tsConfigPath?: string): TsConfig {
338304
let config: TsConfig = null;
339305
tsConfigPath = tsConfigPath || getTsConfigPath(context);
@@ -383,15 +349,11 @@ export function transpileTsString(context: BuildContext, filePath: string, strin
383349
reportDiagnostics: true,
384350
};
385351

352+
transpileOptions.compilerOptions.allowJs = true;
386353
transpileOptions.compilerOptions.sourceMap = true;
387354

388-
// let's manually transpile just this one ts file
389-
// since it is an update, it's in memory already
390-
const sourceText = context.fileCache.get(filePath).content;
391-
392355
// transpile this one module
393-
const transpileOutput = ts.transpileModule(sourceText, transpileOptions);
394-
return transpileOutput;
356+
return ts.transpileModule(stringToTranspile, transpileOptions);
395357
}
396358

397359

src/uglifyjs.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,17 @@ export function uglifyjsWorkerImpl(context: BuildContext, uglifyJsConfig: Uglify
6363

6464
function runUglifyInternal(uglifyJsConfig: UglifyJsConfig): uglify.MinifyOutput {
6565
return uglify.minify(uglifyJsConfig.sourceFile, {
66-
compress: uglifyJsConfig.compress,
66+
compress: {
67+
unused: true,
68+
dead_code: true,
69+
toplevel: true
70+
},
6771
mangle: uglifyJsConfig.mangle,
6872
inSourceMap : uglifyJsConfig.inSourceMap,
6973
outSourceMap: uglifyJsConfig.outSourceMap
7074
});
7175
}
7276

73-
7477
export const taskInfo: TaskInfo = {
7578
fullArg: '--uglifyjs',
7679
shortArg: '-u',

src/util/config.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ describe('config', () => {
8282
expect(context.nodeModulesDir).toEqual(join(process.cwd(), Constants.NODE_MODULES));
8383
expect(context.ionicAngularDir).toEqual(join(process.cwd(), Constants.NODE_MODULES, Constants.IONIC_ANGULAR));
8484
expect(fakeConfig[Constants.ENV_VAR_AT_ANGULAR_DIR]).toEqual(join(process.cwd(), Constants.NODE_MODULES, Constants.AT_ANGULAR));
85+
expect(fakeConfig[Constants.ENV_VAR_RXJS_DIR]).toEqual(join(process.cwd(), Constants.NODE_MODULES, Constants.RXJS));
8586
expect(fakeConfig[Constants.ENV_VAR_IONIC_ANGULAR_TEMPLATE_DIR]).toEqual(join(context.ionicAngularDir, 'templates'));
8687
expect(context.platform).toEqual(null);
8788
expect(context.target).toEqual(null);

src/util/config.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,10 @@ export function generateContext(context?: BuildContext): BuildContext {
119119
setProcessEnvVar(Constants.ENV_VAR_AT_ANGULAR_DIR, angularDir);
120120
Logger.debug(`angularDir set to ${angularDir}`);
121121

122+
const rxjsDir = resolve(getConfigValue(context, '--rxjsDir', null, Constants.ENV_VAR_RXJS_DIR, Constants.ENV_VAR_RXJS_DIR.toLowerCase(), join(context.nodeModulesDir, Constants.RXJS)));
123+
setProcessEnvVar(Constants.ENV_VAR_RXJS_DIR, rxjsDir);
124+
Logger.debug(`rxjsDir set to ${rxjsDir}`);
125+
122126
const ionicAngularTemplatesDir = join(context.ionicAngularDir, 'templates');
123127
setProcessEnvVar(Constants.ENV_VAR_IONIC_ANGULAR_TEMPLATE_DIR, ionicAngularTemplatesDir);
124128
Logger.debug(`ionicAngularTemplatesDir set to ${ionicAngularTemplatesDir}`);
@@ -195,6 +199,10 @@ export function generateContext(context?: BuildContext): BuildContext {
195199
setProcessEnvVar(Constants.ENV_WEBPACK_LOADER, webpackLoaderPath);
196200
Logger.debug(`webpackLoaderPath set to ${webpackLoaderPath}`);
197201

202+
const webpackTranspileLoaderPath = join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'transpile-loader.js');
203+
setProcessEnvVar(Constants.ENV_WEBPACK_TRANSPILE_LOADER, webpackTranspileLoaderPath);
204+
Logger.debug(`webpackTranspileLoaderPath set to ${webpackTranspileLoaderPath}`);
205+
198206
const optimizationLoaderPath = join(getProcessEnvVar(Constants.ENV_VAR_APP_SCRIPTS_DIR), 'dist', 'webpack', 'optimization-loader.js');
199207
setProcessEnvVar(Constants.ENV_OPTIMIZATION_LOADER, optimizationLoaderPath);
200208
Logger.debug(`optimizationLoaderPath set to ${optimizationLoaderPath}`);
@@ -304,6 +312,7 @@ export function generateContext(context?: BuildContext): BuildContext {
304312

305313
// default stand-alone builds to default to es5
306314
// if closure is being used, don't worry about this as it already automatically converts to ES5
315+
307316
const buildToEs5 = getConfigValue(context, '--buildToEs5', null, Constants.ENV_BUILD_TO_ES5, Constants.ENV_BUILD_TO_ES5.toLowerCase(), useExperimentalClosure ? null : 'true');
308317
setProcessEnvVar(Constants.ENV_BUILD_TO_ES5, buildToEs5);
309318
Logger.debug(`buildToEs5 set to ${buildToEs5}`);

0 commit comments

Comments
 (0)