mirror of
https://github.com/coder/coder.git
synced 2025-07-12 00:14:10 +00:00
feat: Add code splitting to reduce bundle size (#1285)
This splits our pages to use separate JavaScript bundles. It initially splits the terminal, which reduces our primary bundle size by ~400KB. We should do this for all pages, but that can come in a future change. This leaves the loading page empty for now, which I think is fine. None of our pages are large enough that the blank screen temporarily would be concerning.
This commit is contained in:
@ -17,49 +17,82 @@ import { SettingsPage } from "./pages/SettingsPage/SettingsPage"
|
||||
import { CreateWorkspacePage } from "./pages/TemplatesPages/OrganizationPage/TemplatePage/CreateWorkspacePage"
|
||||
import { TemplatePage } from "./pages/TemplatesPages/OrganizationPage/TemplatePage/TemplatePage"
|
||||
import { TemplatesPage } from "./pages/TemplatesPages/TemplatesPage"
|
||||
import { TerminalPage } from "./pages/TerminalPage/TerminalPage"
|
||||
import { CreateUserPage } from "./pages/UsersPage/CreateUserPage/CreateUserPage"
|
||||
import { UsersPage } from "./pages/UsersPage/UsersPage"
|
||||
import { WorkspacePage } from "./pages/WorkspacesPage/WorkspacesPage"
|
||||
|
||||
const TerminalPage = React.lazy(() => import("./pages/TerminalPage/TerminalPage"))
|
||||
|
||||
export const AppRouter: React.FC = () => (
|
||||
<Routes>
|
||||
<Route path="/">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<RequireAuth>
|
||||
<IndexPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="login" element={<LoginPage />} />
|
||||
<Route path="healthz" element={<HealthzPage />} />
|
||||
<Route
|
||||
path="cli-auth"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<CliAuthenticationPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="templates">
|
||||
<React.Suspense fallback={<></>}>
|
||||
<Routes>
|
||||
<Route path="/">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<TemplatesPage />
|
||||
</AuthAndFrame>
|
||||
<RequireAuth>
|
||||
<IndexPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route path=":organization/:template">
|
||||
|
||||
<Route path="login" element={<LoginPage />} />
|
||||
<Route path="healthz" element={<HealthzPage />} />
|
||||
<Route
|
||||
path="cli-auth"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<CliAuthenticationPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="templates">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<TemplatePage />
|
||||
<TemplatesPage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
<Route path=":organization/:template">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<TemplatePage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="create"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<CreateWorkspacePage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
<Route path="workspaces">
|
||||
<Route
|
||||
path=":workspace"
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<WorkspacePage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="users">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<UsersPage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
@ -67,83 +100,53 @@ export const AppRouter: React.FC = () => (
|
||||
path="create"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<CreateWorkspacePage />
|
||||
<CreateUserPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
<Route path="workspaces">
|
||||
<Route
|
||||
path=":workspace"
|
||||
path="orgs"
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<WorkspacePage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
|
||||
<Route path="users">
|
||||
<Route
|
||||
index
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<UsersPage />
|
||||
<OrgsPage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="create"
|
||||
path="settings"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<CreateUserPage />
|
||||
</RequireAuth>
|
||||
<AuthAndFrame>
|
||||
<SettingsPage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
<Route
|
||||
path="orgs"
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<OrgsPage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="settings"
|
||||
element={
|
||||
<AuthAndFrame>
|
||||
<SettingsPage />
|
||||
</AuthAndFrame>
|
||||
}
|
||||
/>
|
||||
|
||||
<Route path="preferences" element={<PreferencesLayout />}>
|
||||
<Route path="account" element={<AccountPage />} />
|
||||
<Route path="security" element={<SecurityPage />} />
|
||||
<Route path="ssh-keys" element={<SSHKeysPage />} />
|
||||
<Route path="linked-accounts" element={<LinkedAccountsPage />} />
|
||||
</Route>
|
||||
|
||||
<Route path=":username">
|
||||
<Route path=":workspace">
|
||||
<Route
|
||||
path="terminal"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<TerminalPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
<Route path="preferences" element={<PreferencesLayout />}>
|
||||
<Route path="account" element={<AccountPage />} />
|
||||
<Route path="security" element={<SecurityPage />} />
|
||||
<Route path="ssh-keys" element={<SSHKeysPage />} />
|
||||
<Route path="linked-accounts" element={<LinkedAccountsPage />} />
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
{/* Using path="*"" means "match anything", so this route
|
||||
<Route path=":username">
|
||||
<Route path=":workspace">
|
||||
<Route
|
||||
path="terminal"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<TerminalPage />
|
||||
</RequireAuth>
|
||||
}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
|
||||
{/* Using path="*"" means "match anything", so this route
|
||||
acts like a catch-all for URLs that we don't have explicit
|
||||
routes for. */}
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
<Route path="*" element={<NotFoundPage />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</React.Suspense>
|
||||
)
|
||||
|
@ -8,7 +8,7 @@ import { TextDecoder, TextEncoder } from "util"
|
||||
import { ReconnectingPTYRequest } from "../../api/types"
|
||||
import { history, MockWorkspaceAgent, render } from "../../testHelpers"
|
||||
import { server } from "../../testHelpers/server"
|
||||
import { Language, TerminalPage } from "./TerminalPage"
|
||||
import TerminalPage, { Language } from "./TerminalPage"
|
||||
|
||||
Object.defineProperty(window, "matchMedia", {
|
||||
writable: true,
|
||||
|
@ -17,7 +17,7 @@ export const Language = {
|
||||
websocketErrorMessagePrefix: "WebSocket failed: ",
|
||||
}
|
||||
|
||||
export const TerminalPage: React.FC<{
|
||||
const TerminalPage: React.FC<{
|
||||
readonly renderer?: XTerm.RendererType
|
||||
}> = ({ renderer }) => {
|
||||
const location = useLocation()
|
||||
@ -200,6 +200,8 @@ export const TerminalPage: React.FC<{
|
||||
)
|
||||
}
|
||||
|
||||
export default TerminalPage
|
||||
|
||||
const useStyles = makeStyles(() => ({
|
||||
overlay: {
|
||||
position: "absolute",
|
||||
|
@ -1,4 +1,8 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["node_modules", "_jest", "**/*.stories.tsx", "**/*.test.tsx"]
|
||||
"exclude": ["node_modules", "_jest", "**/*.stories.tsx", "**/*.test.tsx"],
|
||||
"compilerOptions": {
|
||||
// https://github.com/webpack/webpack/issues/5703#issuecomment-357512412
|
||||
"module": "esnext"
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user