diff --git a/interface/src/AppRouting.tsx b/interface/src/AppRouting.tsx
index 91c8f0945..aee79140d 100644
--- a/interface/src/AppRouting.tsx
+++ b/interface/src/AppRouting.tsx
@@ -1,19 +1,13 @@
-import { type FC, Suspense, lazy, memo, useContext, useEffect, useRef } from 'react';
+import { type FC, memo, useContext, useEffect, useRef } from 'react';
import { Navigate, Route, Routes } from 'react-router';
import { toast } from 'react-toastify';
-import {
- LoadingSpinner,
- RequireAuthenticated,
- RequireUnauthenticated
-} from 'components';
+import AuthenticatedRouting from 'AuthenticatedRouting';
+import SignIn from 'SignIn';
+import { RequireAuthenticated, RequireUnauthenticated } from 'components';
import { Authentication, AuthenticationContext } from 'contexts/authentication';
import { useI18nContext } from 'i18n/i18n-react';
-// Lazy load route components for better code splitting
-const SignIn = lazy(() => import('SignIn'));
-const AuthenticatedRouting = lazy(() => import('AuthenticatedRouting'));
-
interface SecurityRedirectProps {
readonly message: string;
readonly signOut?: boolean;
@@ -45,34 +39,32 @@ const AppRouting: FC = memo(() => {
return (
- }>
-
- }
- />
- }
- />
-
-
-
- }
- />
-
-
-
- }
- />
-
-
+
+ }
+ />
+ }
+ />
+
+
+
+ }
+ />
+
+
+
+ }
+ />
+
);
});
diff --git a/interface/src/AuthenticatedRouting.tsx b/interface/src/AuthenticatedRouting.tsx
index 1be5b0f49..8ace232aa 100644
--- a/interface/src/AuthenticatedRouting.tsx
+++ b/interface/src/AuthenticatedRouting.tsx
@@ -1,86 +1,77 @@
-import { Suspense, lazy, memo, useContext } from 'react';
+import { memo, useContext } from 'react';
import { Navigate, Route, Routes } from 'react-router';
-import { Layout, LoadingSpinner } from 'components';
+import CustomEntities from 'app/main/CustomEntities';
+import Customizations from 'app/main/Customizations';
+import Dashboard from 'app/main/Dashboard';
+import Devices from 'app/main/Devices';
+import Help from 'app/main/Help';
+import Modules from 'app/main/Modules';
+import Scheduler from 'app/main/Scheduler';
+import Sensors from 'app/main/Sensors';
+import UserProfile from 'app/main/UserProfile';
+import APSettings from 'app/settings/APSettings';
+import ApplicationSettings from 'app/settings/ApplicationSettings';
+import DownloadUpload from 'app/settings/DownloadUpload';
+import MqttSettings from 'app/settings/MqttSettings';
+import NTPSettings from 'app/settings/NTPSettings';
+import Settings from 'app/settings/Settings';
+import Network from 'app/settings/network/Network';
+import Security from 'app/settings/security/Security';
+import APStatus from 'app/status/APStatus';
+import Activity from 'app/status/Activity';
+import HardwareStatus from 'app/status/HardwareStatus';
+import MqttStatus from 'app/status/MqttStatus';
+import NTPStatus from 'app/status/NTPStatus';
+import NetworkStatus from 'app/status/NetworkStatus';
+import Status from 'app/status/Status';
+import SystemLog from 'app/status/SystemLog';
+import Version from 'app/status/Version';
+import { Layout } from 'components';
import { AuthenticatedContext } from 'contexts/authentication';
-// Lazy load all route components for better code splitting
-const Dashboard = lazy(() => import('app/main/Dashboard'));
-const Devices = lazy(() => import('app/main/Devices'));
-const Sensors = lazy(() => import('app/main/Sensors'));
-const Help = lazy(() => import('app/main/Help'));
-const Customizations = lazy(() => import('app/main/Customizations'));
-const Scheduler = lazy(() => import('app/main/Scheduler'));
-const CustomEntities = lazy(() => import('app/main/CustomEntities'));
-const Modules = lazy(() => import('app/main/Modules'));
-const UserProfile = lazy(() => import('app/main/UserProfile'));
-
-const Status = lazy(() => import('app/status/Status'));
-const HardwareStatus = lazy(() => import('app/status/HardwareStatus'));
-const Activity = lazy(() => import('app/status/Activity'));
-const SystemLog = lazy(() => import('app/status/SystemLog'));
-const MqttStatus = lazy(() => import('app/status/MqttStatus'));
-const NTPStatus = lazy(() => import('app/status/NTPStatus'));
-const APStatus = lazy(() => import('app/status/APStatus'));
-const NetworkStatus = lazy(() => import('app/status/NetworkStatus'));
-const Version = lazy(() => import('app/status/Version'));
-
-const Settings = lazy(() => import('app/settings/Settings'));
-const ApplicationSettings = lazy(() => import('app/settings/ApplicationSettings'));
-const MqttSettings = lazy(() => import('app/settings/MqttSettings'));
-const NTPSettings = lazy(() => import('app/settings/NTPSettings'));
-const APSettings = lazy(() => import('app/settings/APSettings'));
-const DownloadUpload = lazy(() => import('app/settings/DownloadUpload'));
-const Network = lazy(() => import('app/settings/network/Network'));
-const Security = lazy(() => import('app/settings/security/Security'));
-
const AuthenticatedRouting = memo(() => {
const { me } = useContext(AuthenticatedContext);
return (
- }>
-
- } />
- } />
- } />
- } />
- } />
+
+ } />
+ } />
+ } />
+ } />
+ } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
- {me.admin && (
- <>
- } />
- }
- />
- } />
- } />
- } />
- } />
- } />
+ {me.admin && (
+ <>
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
- } />
- } />
+ } />
+ } />
- } />
- } />
- } />
- >
- )}
+ } />
+ } />
+ } />
+ >
+ )}
- } />
-
-
+ } />
+
);
});
diff --git a/interface/vite.config.ts b/interface/vite.config.ts
index 5c288677c..ff34966b7 100644
--- a/interface/vite.config.ts
+++ b/interface/vite.config.ts
@@ -15,7 +15,7 @@ const REPEAT_CHAR = '=';
const REPEAT_COUNT = 50;
const DEFAULT_OUT_DIR = 'dist';
const ES_TARGET = 'es2020';
-const CHUNK_SIZE_WARNING_LIMIT = 512;
+const CHUNK_SIZE_WARNING_LIMIT = 1024;
const ASSETS_INLINE_LIMIT = 4096;
// Common resolve aliases
@@ -130,87 +130,11 @@ const createBasePlugins = (
return plugins;
};
-// Manual chunk splitting strategy
-const createManualChunks = (detailed = false) => {
- return (id: string): string | undefined => {
- if (id.includes('node_modules')) {
- if (id.includes('preact')) return '@preact';
- if (detailed) {
- if (id.includes('react-router')) return '@react-router';
- if (id.includes('@mui/material')) return '@mui-material';
- if (id.includes('@mui/icons-material')) return '@mui-icons';
- if (id.includes('alova')) return '@alova';
- if (id.includes('typesafe-i18n')) return '@i18n';
- if (id.includes('react-toastify')) return '@toastify';
- if (id.includes('@table-library')) return '@table-library';
- if (id.includes('uuid')) return '@uuid';
- if (id.includes('axios') || id.includes('fetch')) return '@http';
- if (id.includes('lodash') || id.includes('ramda')) return '@utils';
- }
- return 'vendor';
- }
- if (detailed) {
- // Group circularly dependent modules together to avoid circular chunk warnings
- // components, app, and utils are tightly coupled, so combine them
- if (
- id.includes('components/') ||
- id.includes('app/') ||
- id.includes('utils/')
- ) {
- return 'app';
- }
- // Keep api separate as it's typically more independent
- if (id.includes('api/')) return 'api';
- }
- return undefined;
- };
+const manualChunks = (id: string): string | undefined => {
+ if (id.includes('node_modules')) return 'vendor';
+ return undefined;
};
-// Rolldown-native codeSplitting groups for the production build.
-// See: https://rolldown.rs/reference/outputoptions.codesplitting
-const createRolldownCodeSplitting = () => ({
- groups: [
- { name: '@preact', test: /[\\/]node_modules[\\/].*preact/, priority: 100 },
- {
- name: '@react-router',
- test: /[\\/]node_modules[\\/].*react-router/,
- priority: 95
- },
- {
- name: '@mui-material',
- test: /[\\/]node_modules[\\/]@mui[\\/]material/,
- priority: 95
- },
- {
- name: '@mui-icons',
- test: /[\\/]node_modules[\\/]@mui[\\/]icons-material/,
- priority: 95
- },
- { name: '@alova', test: /[\\/]node_modules[\\/].*alova/, priority: 90 },
- { name: '@i18n', test: /[\\/]node_modules[\\/].*typesafe-i18n/, priority: 90 },
- {
- name: '@toastify',
- test: /[\\/]node_modules[\\/].*react-toastify/,
- priority: 90
- },
- {
- name: '@table-library',
- test: /[\\/]node_modules[\\/]@table-library/,
- priority: 90
- },
- { name: 'vendor', test: /[\\/]node_modules[\\/]/, priority: 10 },
- // Collapse the lazy-loaded route stubs + shared app/components/utils
- // code into one chunk. This cuts firmware-side route count roughly in
- // half and speeds up route-matching on every incoming HTTP request.
- {
- name: 'app',
- test: /[\\/](app|components|utils)[\\/]/,
- priority: 5
- },
- { name: 'api', test: /[\\/]api[\\/]/, priority: 5 }
- ]
-});
-
// Common build base configuration
const createBaseBuildConfig = () => ({
target: ES_TARGET,
@@ -335,7 +259,7 @@ export default defineConfig(
moduleSideEffects: false
},
output: {
- manualChunks: createManualChunks(false)
+ manualChunks
}
}
}
@@ -375,17 +299,10 @@ export default defineConfig(
chunkFileNames: 'assets/[name]-[hash].js',
entryFileNames: 'assets/[name]-[hash].js',
assetFileNames: 'assets/[name]-[hash].[ext]',
- // Kept as a no-op for documentation/fallback. With Vite 8
- manualChunks: createManualChunks(true),
+ manualChunks,
sourcemap: false
}
- },
- rolldownOptions: {
- output: {
- codeSplitting: createRolldownCodeSplitting()
- }
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- } as any
+ }
}
};
}