Merge pull request #173 from Worklenz/imp/task-list-performance-fixes

feat(lazy-loading): implement lazy loading and suspense for improved …
This commit is contained in:
Chamika J
2025-06-21 19:17:54 +05:30
committed by GitHub
5 changed files with 32 additions and 18 deletions

View File

@@ -13,7 +13,7 @@
<title>Worklenz</title> <title>Worklenz</title>
<!-- Environment configuration --> <!-- Environment configuration -->
<script src="/env-config.js"></script> <script type="module" src="/env-config.js"></script>
<!-- Unregister service worker --> <!-- Unregister service worker -->
<script src="/unregister-sw.js"></script> <script src="/unregister-sw.js"></script>
<!-- Microsoft Clarity --> <!-- Microsoft Clarity -->

View File

@@ -1,10 +1,16 @@
import React from 'react'; import React, { lazy, Suspense } from 'react';
import { RouteObject } from 'react-router-dom'; import { RouteObject } from 'react-router-dom';
import NotFoundPage from '@/pages/404-page/404-page'; import { SuspenseFallback } from '@/components/suspense-fallback/suspense-fallback';
const NotFoundPage = lazy(() => import('@/pages/404-page/404-page'));
const notFoundRoute: RouteObject = { const notFoundRoute: RouteObject = {
path: '*', path: '*',
element: <NotFoundPage />, element: (
<Suspense fallback={<SuspenseFallback />}>
<NotFoundPage />
</Suspense>
),
}; };
export default notFoundRoute; export default notFoundRoute;

View File

@@ -1,6 +1,7 @@
import { useEffect, useState, useRef, useCallback } from 'react'; import { useEffect, useState, useRef, useMemo, useCallback, lazy, Suspense } from 'react';
import { useAppSelector } from '@/hooks/useAppSelector'; import { useAppSelector } from '@/hooks/useAppSelector';
import TaskListFilters from '../taskList/task-list-filters/task-list-filters';
const TaskListFilters = lazy(() => import('../taskList/task-list-filters/task-list-filters'));
import { Flex, Skeleton } from 'antd'; import { Flex, Skeleton } from 'antd';
import BoardSectionCardContainer from './board-section/board-section-container'; import BoardSectionCardContainer from './board-section/board-section-container';
import { import {
@@ -553,7 +554,9 @@ const ProjectViewBoard = () => {
return ( return (
<Flex vertical gap={16}> <Flex vertical gap={16}>
<Suspense fallback={<div>Loading filters...</div>}>
<TaskListFilters position={'board'} /> <TaskListFilters position={'board'} />
</Suspense>
<Skeleton active loading={isLoading} className='mt-4 p-4'> <Skeleton active loading={isLoading} className='mt-4 p-4'>
<DndContext <DndContext
sensors={sensors} sensors={sensors}

View File

@@ -1,9 +1,9 @@
import { useEffect, useState, useMemo } from 'react'; import { useEffect, useState, useMemo, lazy, Suspense } from 'react';
import Flex from 'antd/es/flex'; import Flex from 'antd/es/flex';
import Skeleton from 'antd/es/skeleton'; import Skeleton from 'antd/es/skeleton';
import { useSearchParams } from 'react-router-dom'; import { useSearchParams } from 'react-router-dom';
import TaskListFilters from './task-list-filters/task-list-filters'; const TaskListFilters = lazy(() => import('./task-list-filters/task-list-filters'));
import TaskGroupWrapperOptimized from './task-group-wrapper-optimized'; import TaskGroupWrapperOptimized from './task-group-wrapper-optimized';
import { useAppSelector } from '@/hooks/useAppSelector'; import { useAppSelector } from '@/hooks/useAppSelector';
import { useAppDispatch } from '@/hooks/useAppDispatch'; import { useAppDispatch } from '@/hooks/useAppDispatch';
@@ -100,7 +100,9 @@ const ProjectViewTaskList = () => {
return ( return (
<Flex vertical gap={16} style={{ overflowX: 'hidden' }}> <Flex vertical gap={16} style={{ overflowX: 'hidden' }}>
{/* Filters load independently and don't block the main content */} {/* Filters load independently and don't block the main content */}
<Suspense fallback={<div>Loading filters...</div>}>
<TaskListFilters position="list" /> <TaskListFilters position="list" />
</Suspense>
{isEmptyState ? ( {isEmptyState ? (
<Empty description="No tasks group found" /> <Empty description="No tasks group found" />

View File

@@ -72,7 +72,7 @@ export default defineConfig(({ command, mode }) => {
output: { output: {
// **Optimized Chunking Strategy** // **Optimized Chunking Strategy**
manualChunks(id) { manualChunks(id) {
// Core React libraries // Core React libraries - keep together to avoid dependency issues
if (id.includes('react') || id.includes('react-dom')) { if (id.includes('react') || id.includes('react-dom')) {
return 'react-vendor'; return 'react-vendor';
} }
@@ -82,16 +82,11 @@ export default defineConfig(({ command, mode }) => {
return 'react-router'; return 'react-router';
} }
// Ant Design (keep separate for better caching) // Ant Design and Icons together to share React context
if (id.includes('antd') && !id.includes('@ant-design/icons')) { if (id.includes('antd') || id.includes('@ant-design/icons')) {
return 'antd'; return 'antd';
} }
// Icons (if using ant design icons)
if (id.includes('@ant-design/icons')) {
return 'antd-icons';
}
// Internationalization // Internationalization
if (id.includes('i18next')) { if (id.includes('i18next')) {
return 'i18n'; return 'i18n';
@@ -124,6 +119,9 @@ export default defineConfig(({ command, mode }) => {
// **External dependencies (if any should be externalized)** // **External dependencies (if any should be externalized)**
external: [], external: [],
// **Preserve modules to avoid context issues**
preserveEntrySignatures: 'strict',
}, },
// **Experimental features for better performance** // **Experimental features for better performance**
@@ -138,10 +136,15 @@ export default defineConfig(({ command, mode }) => {
include: [ include: [
'react', 'react',
'react-dom', 'react-dom',
'react/jsx-runtime',
'antd',
'@ant-design/icons',
], ],
exclude: [ exclude: [
// Add any packages that should not be pre-bundled // Add any packages that should not be pre-bundled
], ],
// Force pre-bundling to avoid runtime issues
force: true,
}, },
// **Define global constants** // **Define global constants**