mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-17 06:16:59 +08:00
perf(core): load all pages after 10s (#4834)
This commit is contained in:
@@ -6,6 +6,8 @@ import { ReferencePage } from '../components/reference-page';
|
||||
import type { FavoriteListProps } from '../index';
|
||||
import EmptyItem from './empty-item';
|
||||
|
||||
const emptyPageIdSet = new Set<string>();
|
||||
|
||||
export const FavoriteList = ({ workspace }: FavoriteListProps) => {
|
||||
const metas = useBlockSuitePageMeta(workspace);
|
||||
|
||||
@@ -35,7 +37,7 @@ export const FavoriteList = ({ workspace }: FavoriteListProps) => {
|
||||
metaMapping={metaMapping}
|
||||
pageId={pageMeta.id}
|
||||
// memo?
|
||||
parentIds={new Set()}
|
||||
parentIds={emptyPageIdSet}
|
||||
workspace={workspace}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
rootWorkspacesMetadataAtom,
|
||||
} from '@affine/workspace/atom';
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import type { DragEndEvent } from '@dnd-kit/core';
|
||||
import {
|
||||
DndContext,
|
||||
@@ -29,6 +30,7 @@ import {
|
||||
useSensors,
|
||||
} from '@dnd-kit/core';
|
||||
import { useBlockSuitePageMeta } from '@toeverything/hooks/use-block-suite-page-meta';
|
||||
import { loadPage } from '@toeverything/hooks/use-block-suite-workspace-page';
|
||||
import { currentWorkspaceIdAtom } from '@toeverything/infra/atom';
|
||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||
import { nanoid } from 'nanoid';
|
||||
@@ -119,6 +121,29 @@ type WorkspaceLayoutProps = {
|
||||
incompatible?: boolean;
|
||||
};
|
||||
|
||||
// fix https://github.com/toeverything/AFFiNE/issues/4825
|
||||
function useLoadWorkspacePages() {
|
||||
const [currentWorkspace] = useCurrentWorkspace();
|
||||
const pageMetas = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
|
||||
useEffect(() => {
|
||||
if (currentWorkspace) {
|
||||
const timer = setTimeout(() => {
|
||||
const pageIds = pageMetas.map(meta => meta.id);
|
||||
const pages = pageIds
|
||||
.map(id => currentWorkspace.blockSuiteWorkspace.getPage(id))
|
||||
.filter((p): p is Page => !!p);
|
||||
pages.forEach(page => {
|
||||
loadPage(page, -10);
|
||||
});
|
||||
}, 10 * 1000); // load pages after 10s
|
||||
return () => {
|
||||
clearTimeout(timer);
|
||||
};
|
||||
}
|
||||
return;
|
||||
}, [currentWorkspace, pageMetas]);
|
||||
}
|
||||
|
||||
export const WorkspaceLayout = function WorkspacesSuspense({
|
||||
children,
|
||||
incompatible = false,
|
||||
@@ -237,6 +262,8 @@ export const WorkspaceLayoutInner = ({
|
||||
const inTrashPage = pageMeta?.trash ?? false;
|
||||
const setMainContainer = useSetAtom(mainContainerAtom);
|
||||
|
||||
useLoadWorkspacePages();
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* This DndContext is used for drag page from all-pages list into a folder in sidebar */}
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
"foxact": "^0.2.20",
|
||||
"jotai": "^2.4.3",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"p-queue": "^7.4.1",
|
||||
"react": "18.2.0",
|
||||
"swr": "2.2.4",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@affine/debug": "workspace:*",
|
||||
"@affine/env": "workspace:*",
|
||||
"@blocksuite/block-std": "0.0.0-20231101080734-aa27dc89-nightly",
|
||||
"@blocksuite/blocks": "0.0.0-20231101080734-aa27dc89-nightly",
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
import { DebugLogger } from '@affine/debug';
|
||||
import { assertExists, DisposableGroup } from '@blocksuite/global/utils';
|
||||
import type { Page, Workspace } from '@blocksuite/store';
|
||||
import type { Atom } from 'jotai';
|
||||
import { atom, useAtomValue } from 'jotai';
|
||||
import PQueue from 'p-queue';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
const logger = new DebugLogger('use-block-suite-workspace-page');
|
||||
|
||||
const weakMap = new WeakMap<Workspace, Map<string, Atom<Page | null>>>();
|
||||
|
||||
const emptyAtom = atom<Page | null>(null);
|
||||
@@ -45,6 +49,52 @@ function getAtom(w: Workspace, pageId: string | null): Atom<Page | null> {
|
||||
return map.get(pageId) as Atom<Page | null>;
|
||||
}
|
||||
}
|
||||
// concurrently load 3 pages at most
|
||||
const CONCURRENT_JOBS = 3;
|
||||
|
||||
const loadPageQueue = new PQueue({
|
||||
concurrency: CONCURRENT_JOBS,
|
||||
});
|
||||
|
||||
const loadedPages = new WeakSet<Page>();
|
||||
|
||||
const awaitForIdle = () =>
|
||||
new Promise(resolve =>
|
||||
requestIdleCallback(resolve, {
|
||||
timeout: 1000, // do not wait for too long
|
||||
})
|
||||
);
|
||||
|
||||
const awaitForTimeout = (timeout: number) =>
|
||||
new Promise(resolve => setTimeout(resolve, timeout));
|
||||
|
||||
/**
|
||||
* Load a page and wait for it to be loaded
|
||||
* This page will be loaded in a queue so that it will not jam the network and browser CPU
|
||||
*/
|
||||
export function loadPage(page: Page, priority = 0) {
|
||||
if (loadedPages.has(page)) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
loadedPages.add(page);
|
||||
return loadPageQueue.add(
|
||||
async () => {
|
||||
if (!page.loaded) {
|
||||
await awaitForIdle();
|
||||
await page.waitForLoaded();
|
||||
// we do not know how long it takes to load a page here
|
||||
// so that we just use 300ms timeout as the default page processing time
|
||||
await awaitForTimeout(300);
|
||||
logger.debug('page loaded', page.id);
|
||||
} else {
|
||||
// do nothing if it is already loaded
|
||||
}
|
||||
},
|
||||
{
|
||||
priority,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function useBlockSuiteWorkspacePage(
|
||||
blockSuiteWorkspace: Workspace,
|
||||
@@ -55,8 +105,10 @@ export function useBlockSuiteWorkspacePage(
|
||||
const page = useAtomValue(pageAtom);
|
||||
|
||||
useEffect(() => {
|
||||
if (!page?.loaded) {
|
||||
page?.waitForLoaded().catch(console.error);
|
||||
if (page && !page.loaded) {
|
||||
loadPage(page).catch(err => {
|
||||
logger.error('Failed to load page', err);
|
||||
});
|
||||
}
|
||||
}, [page]);
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../../common/env" },
|
||||
{ "path": "../../common/y-indexeddb" }
|
||||
{ "path": "../../common/y-indexeddb" },
|
||||
{ "path": "../../common/debug" }
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user