diff --git a/package-lock.json b/package-lock.json
index 98a90f4048..d2787f49c8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"@fontsource/noto-sans-tc": "4.5.12",
"@jellyfin/libass-wasm": "4.1.1",
"@jellyfin/sdk": "0.7.0",
+ "@loadable/component": "5.15.2",
"blurhash": "2.0.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.3.2",
@@ -63,6 +64,7 @@
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@types/escape-html": "1.0.2",
+ "@types/loadable__component": "5.13.4",
"@types/lodash-es": "4.17.6",
"@types/react": "17.0.51",
"@types/react-dom": "17.0.17",
@@ -2479,6 +2481,26 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
+ "node_modules/@loadable/component": {
+ "version": "5.15.2",
+ "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.2.tgz",
+ "integrity": "sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==",
+ "dependencies": {
+ "@babel/runtime": "^7.7.7",
+ "hoist-non-react-statics": "^3.3.1",
+ "react-is": "^16.12.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0"
+ }
+ },
"node_modules/@mdn/browser-compat-data": {
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.1.8.tgz",
@@ -2780,6 +2802,15 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "node_modules/@types/loadable__component": {
+ "version": "5.13.4",
+ "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz",
+ "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
"node_modules/@types/lodash": {
"version": "4.14.178",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
@@ -8154,6 +8185,14 @@
"url-toolkit": "^2.1.6"
}
},
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -12674,8 +12713,7 @@
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/react-router": {
"version": "6.4.2",
@@ -20392,6 +20430,16 @@
"integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==",
"dev": true
},
+ "@loadable/component": {
+ "version": "5.15.2",
+ "resolved": "https://registry.npmjs.org/@loadable/component/-/component-5.15.2.tgz",
+ "integrity": "sha512-ryFAZOX5P2vFkUdzaAtTG88IGnr9qxSdvLRvJySXcUA4B4xVWurUNADu3AnKPksxOZajljqTrDEDcYjeL4lvLw==",
+ "requires": {
+ "@babel/runtime": "^7.7.7",
+ "hoist-non-react-statics": "^3.3.1",
+ "react-is": "^16.12.0"
+ }
+ },
"@mdn/browser-compat-data": {
"version": "4.1.8",
"resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-4.1.8.tgz",
@@ -20649,6 +20697,15 @@
"integrity": "sha1-7ihweulOEdK4J7y+UnC86n8+ce4=",
"dev": true
},
+ "@types/loadable__component": {
+ "version": "5.13.4",
+ "resolved": "https://registry.npmjs.org/@types/loadable__component/-/loadable__component-5.13.4.tgz",
+ "integrity": "sha512-YhoCCxyuvP2XeZNbHbi8Wb9EMaUJuA2VGHxJffcQYrJKIKSkymJrhbzsf9y4zpTmr5pExAAEh5hbF628PAZ8Dg==",
+ "dev": true,
+ "requires": {
+ "@types/react": "*"
+ }
+ },
"@types/lodash": {
"version": "4.14.178",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
@@ -24725,6 +24782,14 @@
"url-toolkit": "^2.1.6"
}
},
+ "hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "requires": {
+ "react-is": "^16.7.0"
+ }
+ },
"hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
@@ -27943,8 +28008,7 @@
"react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
- "dev": true
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"react-router": {
"version": "6.4.2",
diff --git a/package.json b/package.json
index ae0d9beead..4b09b3b5a4 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
"@babel/preset-react": "7.18.6",
"@babel/preset-typescript": "7.18.6",
"@types/escape-html": "1.0.2",
+ "@types/loadable__component": "5.13.4",
"@types/lodash-es": "4.17.6",
"@types/react": "17.0.51",
"@types/react-dom": "17.0.17",
@@ -75,6 +76,7 @@
"@fontsource/noto-sans-tc": "4.5.12",
"@jellyfin/libass-wasm": "4.1.1",
"@jellyfin/sdk": "0.7.0",
+ "@loadable/component": "5.15.2",
"blurhash": "2.0.3",
"classlist.js": "https://github.com/eligrey/classList.js/archive/1.2.20180112.tar.gz",
"classnames": "2.3.2",
diff --git a/src/routes/index.tsx b/src/routes/index.tsx
index 4c90fe2dd8..45b18447e3 100644
--- a/src/routes/index.tsx
+++ b/src/routes/index.tsx
@@ -1,47 +1,66 @@
+import loadable from '@loadable/component';
import React from 'react';
import { Navigate, Route, Routes } from 'react-router-dom';
import ConnectionRequired from '../components/ConnectionRequired';
import ServerContentPage from '../components/ServerContentPage';
import { LEGACY_ADMIN_ROUTES, LEGACY_USER_ROUTES, toViewManagerPageRoute } from './legacyRoutes';
-import UserNew from './user/usernew';
-import Search from './search';
-import UserEdit from './user/useredit';
-import UserLibraryAccess from './user/userlibraryaccess';
-import UserParentalControl from './user/userparentalcontrol';
-import UserPassword from './user/userpassword';
-import UserProfile from './user/userprofile';
-import UserProfiles from './user/userprofiles';
-import Home from './home';
-import Movies from './movies';
+
+interface AsyncPageProps {
+ page: string
+}
+
+const AsyncPage = loadable(
+ (props: AsyncPageProps) => import(/* webpackChunkName: "[request]" */ `./${props.page}`),
+ { cacheKey: (props: AsyncPageProps) => props.page }
+);
+
+interface AsyncRoute {
+ path: string
+ page: string
+}
+
+const toAsyncPageRoute = (route: AsyncRoute) => (
+ }
+ />
+);
+
+const USER_ROUTES: AsyncRoute[] = [
+ { path: 'search.html', page: 'search' },
+ { path: 'userprofile.html', page: 'user/userprofile' },
+ { path: 'home.html', page: 'home' },
+ { path: 'movies.html', page: 'movies' }
+];
+
+const ADMIN_ROUTES: AsyncRoute[] = [
+ { path: 'usernew.html', page: 'user/usernew' },
+ { path: 'userprofiles.html', page: 'user/userprofiles' },
+ { path: 'useredit.html', page: 'user/useredit' },
+ { path: 'userlibraryaccess.html', page: 'user/userlibraryaccess' },
+ { path: 'userparentalcontrol.html', page: 'user/userparentalcontrol' },
+ { path: 'userpassword.html', page: 'user/userpassword' }
+];
const AppRoutes = () => (
{/* User routes */}
}>
- } />
- } />
- } />
- } />
-
+ {USER_ROUTES.map(toAsyncPageRoute)}
{LEGACY_USER_ROUTES.map(toViewManagerPageRoute)}
{/* Admin routes */}
}>
- } />
- } />
- } />
- } />
- } />
- } />
+ {ADMIN_ROUTES.map(toAsyncPageRoute)}
+ {LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
} />
-
- {LEGACY_ADMIN_ROUTES.map(toViewManagerPageRoute)}
{/* Public routes */}