Skip to content

Commit

Permalink
When serializing nodes for links, only include small subset of data (#…
Browse files Browse the repository at this point in the history
…944)

Previously, if an AppLink was rendered from a node, the entire node was
serialized. Since a node is a non-trivially large JSON structure, this
resulted in a lot of wasted serialization, as only a few pieces of
information are necessary to generate a link. As a result, pages that
rendered a non-trival amount of links (in this case, SectionHierarchy)
would be very laggy as the browser struggled to do all that
serialization.

This commit filters only those properties necessary to render a link:
`id`, `category`, `name`, and `in_taxon_label`.

(Note that this stretegy is already used in AssociationSummary.vue).

Fixes #912
  • Loading branch information
ptgolden authored Jan 22, 2025
1 parent e939cdc commit 2cc9053
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 5 deletions.
32 changes: 30 additions & 2 deletions frontend/src/global/breadcrumbs.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
import { ref } from "vue";
import { pick } from "lodash";
import type { DirectionalAssociation, Node } from "@/api/model";
import { parse } from "@/util/object";

/**
* This constant represents the minimal set of properties needed to render a
* link to a Node object. If more properties must be added to render such a link
* in the future, add them to this list.
*
* This is necessary because some pages render a large number of links to nodes.
* Each node then must be serialized and inserted into the DOM by Vue. If the
* size of nodes is non-trivial (as in, having lots of related nodes, which is
* not uncommon), then serializing more than ~50 nodes would cause noticeable
* slowdown in the UI. Rendering 1000 nodes would cause the browser to hang for
* about a minute.
*
* To see the issue that initiated this, see:
* https://github.com/monarch-initiative/monarch-app/issues/912
*/
const BREADCRUMB_KEYS = ["id", "category", "name", "in_taxon_label"] as const;

export type BreadcrumbNode = Pick<Node, (typeof BREADCRUMB_KEYS)[number]>;

export type Breadcrumb = {
/** node we're coming from */
node: Partial<Node>;
/* node we're coming from, represented as a small subset of keys defined above */
node: BreadcrumbNode;

/** association between the previous node and the current node */
association: Partial<DirectionalAssociation>;

/**
* whether breadcrumb doesn't have its own history entry (e.g. implicitly
* created sub-class association between current node and association
Expand All @@ -15,6 +37,12 @@ export type Breadcrumb = {
noEntry?: boolean;
};

/* Filter out properties of a node to only include those necessary to render a breadcrumb */
export function toBreadcrumbNode(node: Node) {
const obj: BreadcrumbNode = pick(node, BREADCRUMB_KEYS);
return obj;
}

/** breadcrumbs object for breadcrumbs section on node page */
export const breadcrumbs = ref<Breadcrumb[]>([]);

Expand Down
7 changes: 4 additions & 3 deletions frontend/src/pages/node/SectionHierarchy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
:node="_class"
:breadcrumbs="[
{
node,
node: toBreadcrumbNode(node),
association: {
predicate: 'is super class of',
direction: AssociationDirectionEnum.incoming,
Expand All @@ -40,7 +40,7 @@

<!-- nodes that are "children" of node -->
<AppDetail
title="Sub-classes"
:title="`Sub-classes (${node.node_hierarchy?.sub_classes.length})`"
icon="angle-down"
:blank="!node.node_hierarchy?.sub_classes.length"
:full="true"
Expand All @@ -53,7 +53,7 @@
:node="_class"
:breadcrumbs="[
{
node,
node: toBreadcrumbNode(node),
association: { predicate: 'is sub class of' },
},
]"
Expand All @@ -69,6 +69,7 @@ import { AssociationDirectionEnum, type Node } from "@/api/model";
import AppDetail from "@/components/AppDetail.vue";
import AppDetails from "@/components/AppDetails.vue";
import AppNodeBadge from "@/components/AppNodeBadge.vue";
import { toBreadcrumbNode } from "@/global/breadcrumbs";

type Props = {
/** current node */
Expand Down

0 comments on commit 2cc9053

Please sign in to comment.