From cfc0aa4780a5117f2017e37a425cf34d82ecb9f5 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 19 Nov 2019 12:34:16 -0500 Subject: [PATCH] fix(@angular-devkit/build-angular): properly process es2016+ targets with differential loading A target of es2015 was previously assumed when using differential loading. This could result in erroneously downleveling an es2016+ output file instead of generating a new es5 output file. --- .../build_angular/src/browser/index.ts | 8 +-- .../build_angular/src/utils/action-cache.ts | 4 +- .../build_angular/src/utils/process-bundle.ts | 6 +- .../differential_loading_spec_large.ts | 58 ++++++++++++++++--- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/browser/index.ts b/packages/angular_devkit/build_angular/src/browser/index.ts index e80bf8500c..5f3efe305c 100644 --- a/packages/angular_devkit/build_angular/src/browser/index.ts +++ b/packages/angular_devkit/build_angular/src/browser/index.ts @@ -370,7 +370,7 @@ export function buildWebpackBrowser( } // If not optimizing then ES2015 polyfills do not need processing // Unlike other module scripts, it is never downleveled - const es2015Polyfills = file.file.startsWith('polyfills-es2015'); + const es2015Polyfills = file.file.startsWith('polyfills-es20'); if (!actionOptions.optimize && es2015Polyfills) { continue; } @@ -392,7 +392,7 @@ export function buildWebpackBrowser( if (es5Polyfills) { fs.unlinkSync(filename); - filename = filename.replace('-es2015', ''); + filename = filename.replace(/\-es20\d{2}/, ''); } // Record the bundle processing action @@ -417,8 +417,8 @@ export function buildWebpackBrowser( // Add the newly created ES5 bundles to the index as nomodule scripts const newFilename = es5Polyfills - ? file.file.replace('-es2015', '') - : file.file.replace('es2015', 'es5'); + ? file.file.replace(/\-es20\d{2}/, '') + : file.file.replace(/\-es20\d{2}/, '-es5'); noModuleFiles.push({ ...file, file: newFilename }); } diff --git a/packages/angular_devkit/build_angular/src/utils/action-cache.ts b/packages/angular_devkit/build_angular/src/utils/action-cache.ts index bb8f969520..97c37f9d56 100644 --- a/packages/angular_devkit/build_angular/src/utils/action-cache.ts +++ b/packages/angular_devkit/build_angular/src/utils/action-cache.ts @@ -148,7 +148,7 @@ export class BundleActionCache { cacheEntry = entries[CacheKey.DownlevelCode]; if (cacheEntry) { result.downlevel = { - filename: action.filename.replace('es2015', 'es5'), + filename: action.filename.replace(/\-es20\d{2}/, '-es5'), size: cacheEntry.size, integrity: cacheEntry.integrity, }; @@ -158,7 +158,7 @@ export class BundleActionCache { cacheEntry = entries[CacheKey.DownlevelMap]; if (cacheEntry) { result.downlevel.map = { - filename: action.filename.replace('es2015', 'es5') + '.map', + filename: action.filename.replace(/\-es20\d{2}/, '-es5') + '.map', size: cacheEntry.size, }; diff --git a/packages/angular_devkit/build_angular/src/utils/process-bundle.ts b/packages/angular_devkit/build_angular/src/utils/process-bundle.ts index d8a04314c0..883bb9b2aa 100644 --- a/packages/angular_devkit/build_angular/src/utils/process-bundle.ts +++ b/packages/angular_devkit/build_angular/src/utils/process-bundle.ts @@ -97,7 +97,7 @@ export async function process(options: ProcessBundleOptions): Promise { afterEach(async () => host.restore().toPromise()); - it('emits all the neccessary files', async () => { + it('emits all the neccessary files for default configuration', async () => { const { files } = await browserBuild(architect, host, target); const expectedOutputs = [ @@ -62,6 +62,48 @@ describe('Browser Builder with differential loading', () => { expect(Object.keys(files)).toEqual(jasmine.arrayWithExactContents(expectedOutputs)); }); + it('emits all the neccessary files for target of ES2016', async () => { + host.replaceInFile( + 'tsconfig.json', + '"target": "es2015",', + `"target": "es2016",`, + ); + + const { files } = await browserBuild(architect, host, target); + + const expectedOutputs = [ + 'favicon.ico', + 'index.html', + + 'main-es2016.js', + 'main-es2016.js.map', + 'main-es5.js', + 'main-es5.js.map', + + 'polyfills-es2016.js', + 'polyfills-es2016.js.map', + 'polyfills-es5.js', + 'polyfills-es5.js.map', + + 'runtime-es2016.js', + 'runtime-es2016.js.map', + 'runtime-es5.js', + 'runtime-es5.js.map', + + 'styles-es2016.js', + 'styles-es2016.js.map', + 'styles-es5.js', + 'styles-es5.js.map', + + 'vendor-es2016.js', + 'vendor-es2016.js.map', + 'vendor-es5.js', + 'vendor-es5.js.map', + ] as PathFragment[]; + + expect(Object.keys(files)).toEqual(jasmine.arrayWithExactContents(expectedOutputs)); + }); + it('deactivates differential loading for watch mode', async () => { const { files } = await browserBuild(architect, host, target, { watch: true }); @@ -89,14 +131,12 @@ describe('Browser Builder with differential loading', () => { }); it('emits the right ES formats', async () => { - if (!process.env['NG_BUILD_FULL_DIFFERENTIAL']) { - // The test fails depending on the order of previously executed tests - // The wrong data is being read from the filesystem. - pending('Incredibly flaky outside full build differential loading'); - } - const { files } = await browserBuild(architect, host, target, { optimization: true }); - expect(await files['main-es5.js']).not.toContain('class'); - expect(await files['main-es2015.js']).toContain('class'); + const { files } = await browserBuild(architect, host, target, { + optimization: true, + vendorChunk: false, + }); + expect(await files['main-es5.js']).not.toContain('const '); + expect(await files['main-es2015.js']).toContain('const '); }); it('uses the right zone.js variant', async () => {