Skip to content
This repository has been archived by the owner on Jan 27, 2022. It is now read-only.

fix(explorer): debounce dirty notifications and ignore vendorChunk #264

Merged
merged 1 commit into from Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions angular.json
Expand Up @@ -22,6 +22,7 @@
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"vendorChunk": false,
"aot": true,
"assets": ["src/favicon.ico", "src/assets"],
"styles": [
Expand All @@ -45,7 +46,6 @@
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
Expand Down Expand Up @@ -133,6 +133,7 @@
"main": "projects/shell-chrome/src/main.ts",
"polyfills": "projects/shell-chrome/src/polyfills.ts",
"tsConfig": "projects/shell-chrome/tsconfig.app.json",
"vendorChunk": false,
"aot": true,
"assets": [
"projects/shell-chrome/src/favicon.ico",
Expand All @@ -158,7 +159,6 @@
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
Expand Down
18 changes: 7 additions & 11 deletions projects/ng-devtools-backend/src/lib/change-detection-tracker.ts
@@ -1,20 +1,14 @@
import { buildDirectiveForest, ComponentTreeNode } from './component-tree';
import { runOutsideAngular, patchTemplate } from './utils';
import { Subject } from 'rxjs';

let hookInitialized = false;
export const onChangeDetection$ = new Subject();

export const onChangeDetection = (callback: () => void): void => {
if (hookInitialized) {
return;
}
const forest = buildDirectiveForest();
listenAndNotifyOnUpdates(forest, callback);
hookInitialized = true;
};
const forest = buildDirectiveForest();

// We patch the component tView template function reference
// to detect when the change detection has completed and notify the client.
const listenAndNotifyOnUpdates = (roots: ComponentTreeNode[], callback: () => void): void => {
const listenAndNotifyOnUpdates = (roots: ComponentTreeNode[]): void => {
roots.forEach((root) => {
const { component } = root;
if (!component) {
Expand All @@ -23,8 +17,10 @@ const listenAndNotifyOnUpdates = (roots: ComponentTreeNode[], callback: () => vo
}
patchTemplate(component.instance, () => {
runOutsideAngular(() => {
setTimeout(callback, 0);
setTimeout(() => onChangeDetection$.next(), 0);
});
});
});
};

listenAndNotifyOnUpdates(forest);
Expand Up @@ -9,7 +9,7 @@ import {
ProfilerFrame,
ComponentExplorerViewQuery,
} from 'protocol';
import { onChangeDetection } from './change-detection-tracker';
import { onChangeDetection$ } from './change-detection-tracker';
import { ComponentTreeNode, getLatestComponentState, queryDirectiveForest, updateState } from './component-tree';
import { start as startProfiling, stop as stopProfiling } from './observer';
import { serializeDirectiveState } from './state-serializer/state-serializer';
Expand All @@ -18,6 +18,7 @@ import { setConsoleReference } from './selected-component';
import { unHighlight } from './highlighter';
import { getAngularVersion, appIsAngularInDevMode, appIsSupportedAngularVersion } from './angular-check';
import { observeDOM, getDirectiveId, getDirectiveForest, indexDirectiveForest } from './component-tree-identifiers';
import { debounceTime } from 'rxjs/operators';

export const subscribeToClientEvents = (messageBus: MessageBus<Events>): void => {
messageBus.on('shutdown', shutdownCallback(messageBus));
Expand All @@ -37,7 +38,11 @@ export const subscribeToClientEvents = (messageBus: MessageBus<Events>): void =>

if (appIsAngularInDevMode() && appIsSupportedAngularVersion()) {
setupInspector(messageBus);
onChangeDetection(() => messageBus.emit('componentTreeDirty'));
// Often websites have `scroll` event listener which triggers
// Angular's change detection. We don't want to constantly send
// update requests, instead we want to request an update at most
// every 50ms
onChangeDetection$.pipe(debounceTime(50)).subscribe(() => messageBus.emit('componentTreeDirty'));
}
};

Expand Down
Expand Up @@ -55,6 +55,8 @@ export class DirectiveExplorerComponent implements OnInit {

private _changeSize = new Subject<Event>();
private _clickedElement: IndexedNode | null = null;
private _refreshRetryTimeout: any = null;

parents: FlatNode[] | null = null;

@ViewChild(DirectiveForestComponent) directiveForest: DirectiveForestComponent;
Expand Down Expand Up @@ -114,8 +116,15 @@ export class DirectiveExplorerComponent implements OnInit {

refresh(): void {
const success = this._messageBus.emit('getLatestComponentExplorerView', [this._constructViewQuery()]);
if (!success) {
setTimeout(() => this.refresh(), 500);
// If the event was not throttled, we no longer need to retry.
if (success) {
clearTimeout(this._refreshRetryTimeout);
this._refreshRetryTimeout = null;
return;
}
// If the event was throttled and we haven't scheduled a retry yet.
if (!this._refreshRetryTimeout) {
this._refreshRetryTimeout = setTimeout(() => this.refresh(), 500);
}
}

Expand Down