Skip to content

Commit 7491ac4

Browse files
AlinaVarkkiDevtools-frontend LUCI CQ
authored andcommitted
Agentize 'Duplicate JS' Insight
Example response: https://screenshot.googleplex.com/DH2UPEGnnsPzoni Bug: 425274647 Change-Id: Ie1b14e7da4fefc8fb6ec6138c8dd21450e7ec323 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6770519 Reviewed-by: Connor Clark <[email protected]> Auto-Submit: Alina Varkki <[email protected]> Commit-Queue: Alina Varkki <[email protected]>
1 parent 7330dda commit 7491ac4

File tree

6 files changed

+123
-2
lines changed

6 files changed

+123
-2
lines changed

front_end/models/ai_assistance/agents/PerformanceAgent.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,10 @@ export class PerformanceTraceContext extends ConversationContext<TimelineUtils.A
314314
case 'DOMSize':
315315
return [{title: 'How can I reduce the size of my DOM?'}];
316316
case 'DuplicatedJavaScript':
317-
return [{title: 'How do I deduplicate the identified scripts in my bundle?'}];
317+
return [
318+
{title: 'How do I deduplicate the identified scripts in my bundle?'},
319+
{title: 'Which duplicated JavaScript modules are the most problematic?'}
320+
];
318321
case 'FontDisplay':
319322
return [
320323
{title: 'How can I update my CSS to avoid layout shifts caused by incorrect `font-display` properties?'}

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.test.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,4 +592,92 @@ Response headers
592592
'headers');
593593
});
594594
});
595+
596+
describe('Duplicated javascript', () => {
597+
it('serializes the correct details', async function() {
598+
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'dupe-js.json.gz');
599+
assert.isOk(insights);
600+
const firstNav = getFirstOrError(parsedTrace.Meta.navigationsByNavigationId.values());
601+
const insight = getInsightOrError('DuplicatedJavaScript', insights, firstNav);
602+
const formatter = new PerformanceInsightFormatter(parsedTrace, insight);
603+
const output = formatter.formatInsight();
604+
605+
const expected = `## Insight Title: Duplicated JavaScript
606+
607+
## Insight Summary:
608+
This insight identifies large, duplicated JavaScript modules that are present in your application and create redundant code.
609+
This wastes network bandwidth and slows down your page, as the user's browser must download and process the same code multiple times.
610+
611+
## Detailed analysis:
612+
Total wasted bytes: 615821 bytes.
613+
614+
Duplication grouped by Node modules: - Source: node_modules/filestack-js - Duplicated bytes: 345779 bytes
615+
- Source: node_modules/@headlessui/react - Duplicated bytes: 46023 bytes
616+
- Source: node_modules/react-query - Duplicated bytes: 32976 bytes
617+
- Source: node_modules/@floating-ui/react-dom-interactions - Duplicated bytes: 26253 bytes
618+
- Source: node_modules/yup - Duplicated bytes: 22581 bytes
619+
- Source: node_modules/lodash - Duplicated bytes: 21453 bytes
620+
- Source: node_modules/@formatjs/icu-messageformat-parser - Duplicated bytes: 20835 bytes
621+
- Source: node_modules/react-hook-form - Duplicated bytes: 17328 bytes
622+
- Source: node_modules/@popperjs/core - Duplicated bytes: 15900 bytes
623+
- Source: node_modules/downshift - Duplicated bytes: 14925 bytes
624+
- Source: node_modules/axios - Duplicated bytes: 14079 bytes
625+
- Source: node_modules/react-dropzone - Duplicated bytes: 12180 bytes
626+
- Source: node_modules/@formatjs/intl - Duplicated bytes: 10839 bytes
627+
- Source: node_modules/qs - Duplicated bytes: 9210 bytes
628+
- Source: node_modules/object-inspect - Duplicated bytes: 7254 bytes
629+
- Source: node_modules/history - Duplicated bytes: 6870 bytes
630+
- Source: node_modules/@heroicons/react - Duplicated bytes: 6624 bytes
631+
- Source: node_modules/react-intl - Duplicated bytes: 6534 bytes
632+
- Source: node_modules/get-intrinsic - Duplicated bytes: 6411 bytes
633+
- Source: node_modules/@floating-ui/dom - Duplicated bytes: 6147 bytes
634+
- Source: node_modules/@formatjs/icu-skeleton-parser - Duplicated bytes: 5736 bytes
635+
- Source: webpack://ssi/src/components/Autocomplete/Autocomplete.tsx - Duplicated bytes: 5721 bytes
636+
- Source: node_modules/@floating-ui/core - Duplicated bytes: 5661 bytes
637+
- Source: node_modules/intl-messageformat - Duplicated bytes: 5583 bytes
638+
- Source: node_modules/@loadable/component - Duplicated bytes: 4482 bytes
639+
- Source: node_modules/file-selector - Duplicated bytes: 4374 bytes
640+
- Source: node_modules/universal-cookie - Duplicated bytes: 4191 bytes
641+
- Source: node_modules/tabbable - Duplicated bytes: 4146 bytes
642+
- Source: webpack://ssi/src/components/Button/Button.tsx - Duplicated bytes: 3711 bytes
643+
- Source: node_modules/path-to-regexp - Duplicated bytes: 2865 bytes
644+
- Source: webpack://ssi/src/components/Link/Link.tsx - Duplicated bytes: 2766 bytes
645+
- Source: node_modules/isomorphic-style-loader - Duplicated bytes: 2520 bytes
646+
- Source: webpack://ssi/src/components/Menu/MenuBase.tsx - Duplicated bytes: 2415 bytes
647+
- Source: node_modules/tslib - Duplicated bytes: 2376 bytes
648+
- Source: node_modules/compute-scroll-into-view - Duplicated bytes: 2166 bytes
649+
- Source: node_modules/react-router-dom - Duplicated bytes: 2154 bytes
650+
- Source: node_modules/react-fast-compare - Duplicated bytes: 1935 bytes
651+
- Source: node_modules/react-is - Duplicated bytes: 1845 bytes
652+
- Source: node_modules/react-router - Duplicated bytes: 1788 bytes
653+
- Source: node_modules/css-loader - Duplicated bytes: 1608 bytes
654+
- Source: node_modules/mini-create-react-context - Duplicated bytes: 1563 bytes
655+
656+
## External resources:
657+
`;
658+
assertStringEquals(output, expected);
659+
});
660+
661+
it('serializes no details if there is no duplicate javascript', async function() {
662+
const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');
663+
assert.isOk(insights);
664+
const firstNav = getFirstOrError(parsedTrace.Meta.navigationsByNavigationId.values());
665+
const insight = getInsightOrError('DuplicatedJavaScript', insights, firstNav);
666+
const formatter = new PerformanceInsightFormatter(parsedTrace, insight);
667+
const output = formatter.formatInsight();
668+
669+
const expected = `## Insight Title: Duplicated JavaScript
670+
671+
## Insight Summary:
672+
This insight identifies large, duplicated JavaScript modules that are present in your application and create redundant code.
673+
This wastes network bandwidth and slows down your page, as the user's browser must download and process the same code multiple times.
674+
675+
## Detailed analysis:
676+
There is no duplicated JavaScript in the page modules
677+
678+
## External resources:
679+
`;
680+
assertStringEquals(output, expected);
681+
});
682+
});
595683
});

front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,26 @@ ${shiftsFormatted.join('\n')}`;
279279
${requestSummary}`;
280280
}
281281

282+
if (Trace.Insights.Models.DuplicatedJavaScript.isDuplicatedJavaScript(this.#insight)) {
283+
const totalWastedBytes = this.#insight.wastedBytes;
284+
const duplicatedScriptsByModule = this.#insight.duplicationGroupedByNodeModules;
285+
286+
if (duplicatedScriptsByModule.size === 0) {
287+
return 'There is no duplicated JavaScript in the page modules';
288+
}
289+
290+
const filesFormatted =
291+
Array.from(duplicatedScriptsByModule)
292+
.map(
293+
([module, duplication]) =>
294+
`- Source: ${module} - Duplicated bytes: ${duplication.estimatedDuplicateBytes} bytes`)
295+
.join('\n');
296+
297+
return `Total wasted bytes: ${totalWastedBytes} bytes.
298+
299+
Duplication grouped by Node modules: ${filesFormatted}`;
300+
}
301+
282302
return '';
283303
}
284304

@@ -345,7 +365,8 @@ ${requestSummary}`;
345365
case 'DOMSize':
346366
return '';
347367
case 'DuplicatedJavaScript':
348-
return '';
368+
return `This insight identifies large, duplicated JavaScript modules that are present in your application and create redundant code.
369+
This wastes network bandwidth and slows down your page, as the user's browser must download and process the same code multiple times.`;
349370
case 'FontDisplay':
350371
return '';
351372
case 'ForcedReflow':

front_end/models/trace/insights/DuplicatedJavaScript.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ function finalize(partialModel: PartialInsightModel<DuplicatedJavaScriptInsightM
6060
};
6161
}
6262

63+
export function isDuplicatedJavaScript(model: InsightModel): model is DuplicatedJavaScriptInsightModel {
64+
return model.insightKey === InsightKeys.DUPLICATE_JAVASCRIPT;
65+
}
66+
6367
export function generateInsight(
6468
parsedTrace: Handlers.Types.ParsedTrace, context: InsightSetContext): DuplicatedJavaScriptInsightModel {
6569
const scripts = parsedTrace.Scripts.scripts.filter(script => {

front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ export class DuplicatedJavaScript extends BaseInsightComponent<DuplicatedJavaScr
3333
return this.model.scripts.some(script => !!script.url);
3434
}
3535

36+
protected override hasAskAiSupport(): boolean {
37+
return true;
38+
}
39+
3640
#openTreemap(): void {
3741
if (!this.model) {
3842
return;

front_end/ui/visual_logging/KnownContextValues.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3710,6 +3710,7 @@ export const knownContextValues = new Set([
37103710
'timeline.insight-ask-ai.dismiss-field-mismatch',
37113711
'timeline.insight-ask-ai.document-latency',
37123712
'timeline.insight-ask-ai.dom-size',
3713+
'timeline.insight-ask-ai.duplicated-javascript ',
37133714
'timeline.insight-ask-ai.field-mismatch',
37143715
'timeline.insight-ask-ai.font-display',
37153716
'timeline.insight-ask-ai.forced-reflow',

0 commit comments

Comments
 (0)