diff --git a/packages/html-templates/src/app/__snapshots__/app.stories.storyshot b/packages/html-templates/src/app/__snapshots__/app.stories.storyshot
index 4e6f05a92c..1400e5337a 100644
--- a/packages/html-templates/src/app/__snapshots__/app.stories.storyshot
+++ b/packages/html-templates/src/app/__snapshots__/app.stories.storyshot
@@ -72,6 +72,27 @@ exports[`Storyshots App default 1`] = `
},
"type": "error",
},
+ "newAssets": Object {
+ "data": Object {
+ "assets": Array [
+ "assets/auth.js",
+ "assets/auth.css",
+ "assets/home.css",
+ "assets/home.js",
+ "assets/home~organization~project.css",
+ "assets/home~organization~project.js",
+ "assets/organization~project~setup.js",
+ "assets/organization~setup.js",
+ "assets/organization~setup.css",
+ "assets/runtime~main.js",
+ "assets/setup.css",
+ "assets/setup.js",
+ "index.html",
+ ],
+ "text": "Bundle introduced 13 new assets",
+ },
+ "type": "warning",
+ },
"newPackages": Object {
"changes": true,
"data": Object {
@@ -89802,6 +89823,40 @@ exports[`Storyshots App multiple baselines 1`] = `
},
"type": "error",
},
+ "newAssets": Object {
+ "data": Object {
+ "assets": Array [
+ "404.html",
+ "android-chrome-192x192.png",
+ "android-chrome-512x512.png",
+ "apple-touch-icon.png",
+ "assets/auth.js",
+ "assets/auth.css",
+ "assets/home.css",
+ "assets/home.js",
+ "assets/home~organization~project.css",
+ "assets/home~organization~project.js",
+ "assets/organization~project~setup.js",
+ "assets/organization~setup.js",
+ "assets/organization~setup.css",
+ "assets/runtime~main.js",
+ "assets/setup.css",
+ "assets/setup.js",
+ "browserconfig.xml",
+ "favicon-16x16.png",
+ "favicon-32x32.png",
+ "favicon.ico",
+ "index.html",
+ "mstile-150x150.png",
+ "logo.svg",
+ "robots.txt",
+ "safari-pinned-tab.svg",
+ "site.webmanifest",
+ ],
+ "text": "Bundle introduced 26 new assets",
+ },
+ "type": "warning",
+ },
"newPackages": Object {
"changes": true,
"data": Object {
@@ -119618,6 +119673,27 @@ exports[`Storyshots App multiple baselines 1`] = `
},
"type": "error",
},
+ "newAssets": Object {
+ "data": Object {
+ "assets": Array [
+ "404.html",
+ "android-chrome-192x192.png",
+ "android-chrome-512x512.png",
+ "apple-touch-icon.png",
+ "browserconfig.xml",
+ "favicon-16x16.png",
+ "favicon-32x32.png",
+ "favicon.ico",
+ "mstile-150x150.png",
+ "logo.svg",
+ "robots.txt",
+ "safari-pinned-tab.svg",
+ "site.webmanifest",
+ ],
+ "text": "Bundle introduced 13 new assets",
+ },
+ "type": "warning",
+ },
"newPackages": Object {
"changes": true,
"data": Object {
@@ -153049,6 +153125,27 @@ exports[`Storyshots App no baseline 1`] = `
},
"type": "error",
},
+ "newAssets": Object {
+ "data": Object {
+ "assets": Array [
+ "assets/auth.js",
+ "assets/auth.css",
+ "assets/home.css",
+ "assets/home.js",
+ "assets/home~organization~project.css",
+ "assets/home~organization~project.js",
+ "assets/organization~project~setup.js",
+ "assets/organization~setup.js",
+ "assets/organization~setup.css",
+ "assets/runtime~main.js",
+ "assets/setup.css",
+ "assets/setup.js",
+ "index.html",
+ ],
+ "text": "Bundle introduced 13 new assets",
+ },
+ "type": "warning",
+ },
"newPackages": Object {
"changes": true,
"data": Object {
diff --git a/packages/utils/src/constants.ts b/packages/utils/src/constants.ts
index c84ec2ca51..edd2291d1f 100644
--- a/packages/utils/src/constants.ts
+++ b/packages/utils/src/constants.ts
@@ -99,6 +99,10 @@ export interface JobInsightNewPackagesData {
packages: Array;
}
+export interface JobInsightNewAssetsData {
+ assets: Array;
+}
+
export type JobSummarySource = Record;
export type JobSummary = JobSection;
@@ -108,6 +112,7 @@ export interface JobInsights {
duplicatePackages?: JobInsight;
duplicatePackagesV3?: JobInsight;
newPackages?: JobInsight;
+ newAssets?: JobInsight;
};
}
diff --git a/packages/utils/src/webpack/extract/__tests__/assets-new-insight.ts b/packages/utils/src/webpack/extract/__tests__/assets-new-insight.ts
new file mode 100644
index 0000000000..176e63282f
--- /dev/null
+++ b/packages/utils/src/webpack/extract/__tests__/assets-new-insight.ts
@@ -0,0 +1,130 @@
+import { extractAssetsNewInsight } from '../assets-new-insight';
+
+describe('Webpack/extracts/extractAssetsNewInsight', () => {
+ test('should return null when there is no baseline', () => {
+ const actual = extractAssetsNewInsight(null, {
+ metrics: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ },
+ },
+ });
+
+ expect(actual).toEqual(null);
+ });
+
+ test('should return null when there are no new assets', () => {
+ const actual = extractAssetsNewInsight(
+ null,
+ {
+ metrics: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ },
+ },
+ },
+ {
+ metrics: {
+ webpack: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ },
+ },
+ },
+ } as any,
+ );
+
+ expect(actual).toEqual(null);
+ });
+
+ test('should return insights when there is a new assets', () => {
+ const actual = extractAssetsNewInsight(
+ null,
+ {
+ metrics: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ './main.css': {
+ size: 100,
+ },
+ },
+ },
+ },
+ {
+ metrics: {
+ webpack: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ },
+ },
+ },
+ } as any,
+ );
+
+ expect(actual).toEqual({
+ insights: {
+ newAssets: {
+ type: 'warning',
+ data: {
+ text: 'Bundle introduced one new asset',
+ assets: ['./main.css'],
+ },
+ },
+ },
+ });
+ });
+
+ test('should return insights when there are new packages', () => {
+ const actual = extractAssetsNewInsight(
+ null,
+ {
+ metrics: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ './main.css': {
+ size: 100,
+ },
+ './logo.png': {
+ size: 100,
+ },
+ },
+ },
+ },
+ {
+ metrics: {
+ webpack: {
+ assets: {
+ './main.js': {
+ size: 100,
+ },
+ },
+ },
+ },
+ } as any,
+ );
+
+ expect(actual).toEqual({
+ insights: {
+ newAssets: {
+ type: 'warning',
+ data: {
+ text: 'Bundle introduced 2 new assets',
+ assets: ['./main.css', './logo.png'],
+ },
+ },
+ },
+ });
+ });
+});
diff --git a/packages/utils/src/webpack/extract/assets-new-insight.ts b/packages/utils/src/webpack/extract/assets-new-insight.ts
new file mode 100644
index 0000000000..c2f8f1a04c
--- /dev/null
+++ b/packages/utils/src/webpack/extract/assets-new-insight.ts
@@ -0,0 +1,51 @@
+import { InsightType, Job, JobInsights } from '../../constants';
+import { Assets } from '../types';
+
+const getAssetNames = (assets: Assets) => new Set(Object.keys(assets));
+
+interface AssetsNewInsight {
+ insights?: {
+ newAssets: JobInsights['webpack']['newAssets'];
+ };
+}
+
+export const extractAssetsNewInsight = (
+ _: any,
+ currentExtractedData: any,
+ baselineJob?: Job,
+): AssetsNewInsight | null => {
+ const currentAssets = currentExtractedData.metrics?.assets as Assets;
+ const baselineAssets = baselineJob?.metrics?.webpack?.assets as Assets;
+
+ if (!baselineAssets) {
+ return null;
+ }
+
+ const currentAssetNames = getAssetNames(currentAssets);
+ const baselineAssetNames = getAssetNames(baselineAssets);
+
+ const newAssets: Array = [];
+ currentAssetNames.forEach((assetName) => {
+ if (!baselineAssetNames.has(assetName)) {
+ newAssets.push(assetName);
+ }
+ });
+
+ if (newAssets.length === 0) {
+ return null;
+ }
+
+ const text = `Bundle introduced ${newAssets.length > 1 ? `${newAssets.length} new assets` : 'one new asset' }`;
+
+ return {
+ insights: {
+ newAssets: {
+ type: InsightType.WARNING,
+ data: {
+ text,
+ assets: newAssets,
+ },
+ },
+ },
+ };
+};
diff --git a/packages/utils/src/webpack/extract/index.js b/packages/utils/src/webpack/extract/index.js
index 7901e89a5e..46907eaca7 100644
--- a/packages/utils/src/webpack/extract/index.js
+++ b/packages/utils/src/webpack/extract/index.js
@@ -5,6 +5,7 @@ import { extractAssetsCacheInvalidation } from './assets-cache-invalidation';
import { extractAssetsChunkCount } from './assets-chunk-count';
import { extractAssetsCount } from './assets-count';
import { extractAssetsSize } from './assets-size';
+import { extractAssetsNewInsight } from './assets-new-insight';
import { extractAssetsSizeTotalInsight } from './assets-size-total-insight';
import { extractMeta } from './meta';
import { extractModules } from './modules';
@@ -19,6 +20,7 @@ const extractFns = [
extractAssetsChunkCount,
extractAssetsCount,
extractAssetsSize,
+ extractAssetsNewInsight,
extractAssetsSizeTotalInsight,
extractMeta,
extractModules,