Improve lazy loading (#12393)

Creating manual chunk was a bad idea, we should always solve lazy
loading problem at the source instance.

Setting a 4.5MB for the index bundle size, CI will fail if we go above.

There is still a lot of room for optimizations!
- More agressive lazy loading (e.g. xyflow and tiptap are still loaded
in index!)
- Add a  prefetch mechanism
- Add stronger CI checks to make sure libraries we've set asides are not
added back
- Fix AllIcons component with does not work as intended (loaded on
initial load)
This commit is contained in:
Félix Malfait
2025-06-01 09:33:16 +02:00
committed by GitHub
parent c74d7fe986
commit f6bfec882a
37 changed files with 577 additions and 277 deletions

View File

@ -1,5 +1,4 @@
import { AppErrorBoundaryEffect } from '@/error-handler/components/internal/AppErrorBoundaryEffect';
import { captureException } from '@sentry/react';
import { ErrorInfo, ReactNode } from 'react';
import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
@ -14,11 +13,17 @@ export const AppErrorBoundary = ({
FallbackComponent,
resetOnLocationChange = true,
}: AppErrorBoundaryProps) => {
const handleError = (error: Error, info: ErrorInfo) => {
captureException(error, (scope) => {
scope.setExtras({ info });
return scope;
});
const handleError = async (error: Error, info: ErrorInfo) => {
try {
const { captureException } = await import('@sentry/react');
captureException(error, (scope) => {
scope.setExtras({ info });
return scope;
});
} catch (sentryError) {
// eslint-disable-next-line no-console
console.error('Failed to capture exception with Sentry:', sentryError);
}
};
const handleReset = () => {

View File

@ -1,9 +1,3 @@
import {
browserTracingIntegration,
init,
replayIntegration,
setUser,
} from '@sentry/react';
import { isNonEmptyString } from '@sniptt/guards';
import { useEffect, useState } from 'react';
import { useRecoilValue } from 'recoil';
@ -27,38 +21,74 @@ export const SentryInitEffect = () => {
const [isSentryUserDefined, setIsSentryUserDefined] = useState(false);
useEffect(() => {
if (
!isSentryInitializing &&
isNonEmptyString(sentryConfig?.dsn) &&
!isSentryInitialized
) {
setIsSentryInitializing(true);
init({
environment: sentryConfig?.environment ?? undefined,
release: sentryConfig?.release ?? undefined,
dsn: sentryConfig?.dsn,
integrations: [browserTracingIntegration({}), replayIntegration()],
tracePropagationTargets: ['localhost:3001', REACT_APP_SERVER_BASE_URL],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
const initializeSentry = async () => {
if (
isNonEmptyString(sentryConfig?.dsn) &&
!isSentryInitialized &&
!isSentryInitializing
) {
setIsSentryInitializing(true);
setIsSentryInitialized(true);
setIsSentryInitializing(false);
}
try {
const { init, browserTracingIntegration, replayIntegration } =
await import('@sentry/react');
if (isDefined(currentUser) && !isSentryUserDefined) {
setUser({
email: currentUser?.email,
id: currentUser?.id,
workspaceId: currentWorkspace?.id,
workspaceMemberId: currentWorkspaceMember?.id,
});
setIsSentryUserDefined(true);
} else {
setUser(null);
}
init({
environment: sentryConfig?.environment ?? undefined,
release: sentryConfig?.release ?? undefined,
dsn: sentryConfig?.dsn,
integrations: [browserTracingIntegration({}), replayIntegration()],
tracePropagationTargets: [
'localhost:3001',
REACT_APP_SERVER_BASE_URL,
],
tracesSampleRate: 1.0,
replaysSessionSampleRate: 0.1,
replaysOnErrorSampleRate: 1.0,
});
setIsSentryInitialized(true);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to initialize Sentry:', error);
} finally {
setIsSentryInitializing(false);
}
}
};
const updateSentryUser = async () => {
if (
isSentryInitialized &&
isDefined(currentUser) &&
!isSentryUserDefined
) {
try {
const { setUser } = await import('@sentry/react');
setUser({
email: currentUser?.email,
id: currentUser?.id,
workspaceId: currentWorkspace?.id,
workspaceMemberId: currentWorkspaceMember?.id,
});
setIsSentryUserDefined(true);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to set Sentry user:', error);
}
} else if (!isDefined(currentUser) && isSentryInitialized) {
try {
const { setUser } = await import('@sentry/react');
setUser(null);
} catch (error) {
// eslint-disable-next-line no-console
console.error('Failed to clear Sentry user:', error);
}
}
};
initializeSentry();
updateSentryUser();
}, [
sentryConfig,
isSentryInitialized,
@ -68,5 +98,6 @@ export const SentryInitEffect = () => {
currentWorkspaceMember,
isSentryUserDefined,
]);
return <></>;
};