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.
This commit is contained in:
Charles Lyding 2019-11-19 12:34:16 -05:00 committed by Douglas Parker
parent 5c9fc32ae6
commit cfc0aa4780
4 changed files with 58 additions and 18 deletions

View File

@ -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 });
}

View File

@ -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,
};

View File

@ -97,7 +97,7 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
const basePath = path.dirname(options.filename);
const filename = path.basename(options.filename);
const downlevelFilename = filename.replace('es2015', 'es5');
const downlevelFilename = filename.replace(/\-es20\d{2}/, '-es5');
const downlevel = !options.optimizeOnly;
// if code size is larger than 500kB, manually handle sourcemaps with newer source-map package.
@ -403,9 +403,9 @@ async function processRuntime(
// Adjust lazy loaded scripts to point to the proper variant
// Extra spacing is intentional to align source line positions
downlevelCode = downlevelCode.replace('"-es2015.', ' "-es5.');
downlevelCode = downlevelCode.replace(/"\-es20\d{2}\./, ' "-es5.');
const downlevelFilePath = options.filename.replace('es2015', 'es5');
const downlevelFilePath = options.filename.replace(/\-es20\d{2}/, '-es5');
let downlevelMap;
let result;
if (options.optimize) {

View File

@ -26,7 +26,7 @@ describe('Browser Builder with differential loading', () => {
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 () => {