Skip to content

Commit

Permalink
refactor(@angular-devkit/build-angular): remove Webpack 4 specific ty…
Browse files Browse the repository at this point in the history
…pe casting

Webpack 5 contains improved types and exports that reduce the need to perform additional type casting throughout the internal Webpack plugins.

(cherry picked from commit 5804fec)
  • Loading branch information
clydin authored and alan-agius4 committed Apr 19, 2021
1 parent a6e5103 commit e1b4e40
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 109 deletions.
Expand Up @@ -6,20 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
import { analytics } from '@angular-devkit/core';
import {
Compilation,
Compiler,
Module,
Stats,
sources,
} from 'webpack';

const NormalModule = require('webpack/lib/NormalModule');

interface NormalModule extends Module {
_source?: sources.OriginalSource | null;
resource?: string;
}
import { Compilation, Compiler, Module, NormalModule, Stats } from 'webpack';

const webpackAllErrorMessageRe = /^([^(]+)\(\d+,\d\): (.*)$/gm;
const webpackTsErrorMessageRe = /^[^(]+\(\d+,\d\): error (TS\d+):/;
Expand Down Expand Up @@ -148,21 +135,26 @@ export class NgBuildAnalyticsPlugin {
}

protected _checkTsNormalModule(module: NormalModule) {
if (module._source) {
// PLEASE REMEMBER:
// We're dealing with ES5 _or_ ES2015 JavaScript at this point (we don't know for sure).

// Just count the ngOnInit occurences. Comments/Strings/calls occurences should be sparse
// so we just consider them within the margin of error. We do break on word break though.
this._stats.numberOfNgOnInit += countOccurrences(module._source.source().toString(), 'ngOnInit', true);

// Count the number of `Component({` strings (case sensitive), which happens in __decorate().
this._stats.numberOfComponents += countOccurrences(module._source.source().toString(), 'Component({');
// For Ivy we just count ɵcmp.
this._stats.numberOfComponents += countOccurrences(module._source.source().toString(), '.ɵcmp', true);
// for ascii_only true
this._stats.numberOfComponents += countOccurrences(module._source.source().toString(), '.\u0275cmp', true);
const originalSource = module.originalSource();
if (!originalSource) {
return;
}

const originalContent = originalSource.source().toString();

// PLEASE REMEMBER:
// We're dealing with ES5 _or_ ES2015 JavaScript at this point (we don't know for sure).

// Just count the ngOnInit occurences. Comments/Strings/calls occurences should be sparse
// so we just consider them within the margin of error. We do break on word break though.
this._stats.numberOfNgOnInit += countOccurrences(originalContent, 'ngOnInit', true);

// Count the number of `Component({` strings (case sensitive), which happens in __decorate().
this._stats.numberOfComponents += countOccurrences(originalContent, 'Component({');
// For Ivy we just count ɵcmp.
this._stats.numberOfComponents += countOccurrences(originalContent, '.ɵcmp', true);
// for ascii_only true
this._stats.numberOfComponents += countOccurrences(originalContent, '.\u0275cmp', true);
}

protected _collectErrors(stats: Stats) {
Expand Down Expand Up @@ -231,12 +223,11 @@ export class NgBuildAnalyticsPlugin {
* Reports a succeed module.
* @private
*/
protected _succeedModule(mod: Module) {
protected _succeedModule(module: Module) {
// Only report NormalModule instances.
if (mod.constructor !== NormalModule) {
if (!(module instanceof NormalModule)) {
return;
}
const module = mod as {} as NormalModule;

// Only reports modules that are part of the user's project. We also don't do node_modules.
// There is a chance that someone name a file path `hello_node_modules` or something and we
Expand Down
Expand Up @@ -29,9 +29,7 @@ export class AnyComponentStyleBudgetChecker {
compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation) => {
const afterOptimizeChunkAssets = () => {
// In AOT compilations component styles get processed in child compilations.
// tslint:disable-next-line: no-any
const parentCompilation = (compilation.compiler as any).parentCompilation;
if (!parentCompilation) {
if (!compilation.compiler.parentCompilation) {
return;
}

Expand Down
Expand Up @@ -21,30 +21,17 @@ export interface DedupeModuleResolvePluginOptions {

// tslint:disable-next-line: no-any
function getResourceData(resolveData: any): ResourceData {
if (resolveData.createData) {
// Webpack 5+
const {
descriptionFileData,
relativePath,
} = resolveData.createData.resourceResolveData;

return {
packageName: descriptionFileData?.name,
packageVersion: descriptionFileData?.version,
relativePath,
resource: resolveData.createData.resource,
};
} else {
// Webpack 4
const { resource, resourceResolveData } = resolveData;

return {
packageName: resourceResolveData.descriptionFileData?.name,
packageVersion: resourceResolveData.descriptionFileData?.version,
relativePath: resourceResolveData.relativePath,
resource: resource,
};
}
const {
descriptionFileData,
relativePath,
} = resolveData.createData.resourceResolveData;

return {
packageName: descriptionFileData?.name,
packageVersion: descriptionFileData?.version,
relativePath,
resource: resolveData.createData.resource,
};
}

/**
Expand Down Expand Up @@ -100,14 +87,9 @@ export class DedupeModuleResolvePlugin {
}

// Alter current request with previously resolved module.
// tslint:disable-next-line: no-any
const createData = (result as any).createData;
if (createData) {
createData.resource = prevResource;
createData.userRequest = prevResource;
} else {
result.request = prevRequest;
}
const createData = result.createData as { resource: string; userRequest: string };
createData.resource = prevResource;
createData.userRequest = prevRequest;
});
});
}
Expand Down
Expand Up @@ -21,7 +21,6 @@ export class SuppressExtractedTextChunksWebpackPlugin {

// Only chunks with a css asset should have JavaScript assets removed
let hasCssFile = false;
// chunk.files is an Array in Webpack 4 and a Set in Webpack 5
for (const file of chunk.files) {
if (file.endsWith('.css')) {
hasCssFile = true;
Expand All @@ -35,53 +34,20 @@ export class SuppressExtractedTextChunksWebpackPlugin {

// Only chunks with all CSS entry dependencies should have JavaScript assets removed
let cssOnly = false;
// The any cast is used for default Webpack 4 type compatibility
// tslint:disable-next-line: no-any
const entryModules = (compilation as any).chunkGraph?.getChunkEntryModulesIterable(chunk);
if (entryModules) {
// Webpack 5
for (const module of entryModules) {
cssOnly = module.dependencies.every(
(dependency: {}) => dependency.constructor.name === 'CssDependency',
);
const entryModules = compilation.chunkGraph.getChunkEntryModulesIterable(chunk);
for (const module of entryModules) {
cssOnly = module.dependencies.every(
(dependency: {}) => dependency.constructor.name === 'CssDependency',
);

if (!cssOnly) {
break;
}
}
} else {
// Webpack 4
for (const module of chunk.modulesIterable as Iterable<{ dependencies: {}[] }>) {
cssOnly = module.dependencies.every((dependency) => {
const name = dependency.constructor.name;

return (
name === 'CssDependency' ||
name === 'SingleEntryDependency' ||
name === 'MultiEntryDependency' ||
name === 'HarmonyCompatibilityDependency' ||
name === 'HarmonyExportHeaderDependency' ||
name === 'HarmonyInitDependency'
);
});

if (!cssOnly) {
break;
}
if (!cssOnly) {
break;
}
}

if (cssOnly) {
if (Array.isArray(chunk.files)) {
// Webpack 4
(chunk.files as string[]) = chunk.files.filter((file) => file !== filename);
delete compilation.assets[filename];
} else {
// Webpack 5
// Casting is used for default Webpack 4 type compatibility
((chunk.files as unknown) as Set<string>).delete(filename);
((compilation as unknown) as { deleteAsset(file: string): void }).deleteAsset(filename);
}
chunk.files.delete(filename);
compilation.deleteAsset(filename);
}
});
});
Expand Down

0 comments on commit e1b4e40

Please sign in to comment.