diff --git a/tools/gulp/util/annotate-pure.ts b/tools/gulp/util/annotate-pure.ts new file mode 100644 index 000000000000..e0b0a7fdbc5b --- /dev/null +++ b/tools/gulp/util/annotate-pure.ts @@ -0,0 +1,22 @@ + +const iifeExpression = + new RegExp('^(var (\\S+) = )(\\(function \\(\\) \\{\\n(?: ' + + '(?:\\/\\*\\*| \\*|\\*\\/|\\/\\/)[^\\n]*\\n)* function \\2\\([^\\)]*\\) \\{\\n)', 'mg'); + +/** + * Adds `@__PURE__` annotation comments to IIFEs containing ES5-downleveled classes generated by + * TypeScript so that Uglify can tree-shake classes that are not referenced. + * + * @param fileContent The content of the file for which `@__PURE__` will be added. + * @returns The content of the file with `@__PURE__` annotations added. + */ +export function addPureAnnotations(fileContent: string) { + return fileContent + // Prefix downleveled classes w/ the @__PURE__ annotation. + .replace(iifeExpression, '$1/*@__PURE__*/$3') + // Prefix downleveled classes that extend another class w/ the @__PURE__ annotation + .replace( + /^(var (\S+) = )(\(function \(_super\) \{\n __extends\(\2, _super\);\n)/mg, + '$1/*@__PURE__*/$3' + ); +} diff --git a/tools/gulp/util/package-build.ts b/tools/gulp/util/package-build.ts index 6bddac2f4f3d..a1265c2bc5cd 100644 --- a/tools/gulp/util/package-build.ts +++ b/tools/gulp/util/package-build.ts @@ -10,6 +10,7 @@ import { import { DIST_BUNDLES, DIST_ROOT, SOURCE_ROOT, PROJECT_ROOT, LICENSE_BANNER, MATERIAL_VERSION } from '../constants'; +import {addPureAnnotations} from './annotate-pure'; // There are no type definitions available for these imports. const uglify = require('uglify-js'); @@ -38,6 +39,7 @@ export function composeRelease(packageName: string) { updatePackageVersion(releasePath); createTypingFile(releasePath, packageName); createMetadataFile(releasePath, packageName); + addPureAnnotationCommentsToEs5Bundle(releasePath, packageName); } /** Builds the bundles for the specified package. */ @@ -156,3 +158,12 @@ function inlinePackageMetadataFiles(packagePath: string) { writeFileSync(path , JSON.stringify(metadata), 'utf-8'); }); } + +/** Adds Uglify "@__PURE__" decorations to the generated ES5 bundle. */ +function addPureAnnotationCommentsToEs5Bundle(outputDir: string, entryName: string) { + const es5BundlePath = join(outputDir, '@angular', `${entryName}.es5.js`); + const originalContent = readFileSync(es5BundlePath, 'utf-8'); + const annotatedContent = addPureAnnotations(originalContent); + + writeFileSync(es5BundlePath, annotatedContent, 'utf-8'); +}