mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2026-06-08 13:37:29 +01:00
Copilot changes to improve initial load time.
This commit is contained in:
+57
-32
@@ -2,26 +2,48 @@ import { Spinner, SpinnerSize, TooltipHost } from "@fluentui/react";
|
||||
import { CollectionTabKind } from "Contracts/ViewModels";
|
||||
import Explorer from "Explorer/Explorer";
|
||||
import { useCommandBar } from "Explorer/Menus/CommandBar/CommandBarComponentAdapter";
|
||||
import { QueryCopilotTab } from "Explorer/QueryCopilot/QueryCopilotTab";
|
||||
import { FabricHomeScreen } from "Explorer/SplashScreen/FabricHome";
|
||||
import { SplashScreen } from "Explorer/SplashScreen/SplashScreen";
|
||||
import { ConnectTab } from "Explorer/Tabs/ConnectTab";
|
||||
import { PostgresConnectTab } from "Explorer/Tabs/PostgresConnectTab";
|
||||
import { QuickstartTab } from "Explorer/Tabs/QuickstartTab";
|
||||
import { VcoreMongoConnectTab } from "Explorer/Tabs/VCoreMongoConnectTab";
|
||||
import { VcoreMongoQuickstartTab } from "Explorer/Tabs/VCoreMongoQuickstartTab";
|
||||
import { KeyboardAction, KeyboardActionGroup, useKeyboardActionGroup } from "KeyboardShortcuts";
|
||||
import { isFabricNative } from "Platform/Fabric/FabricUtil";
|
||||
import { userContext } from "UserContext";
|
||||
import { useTeachingBubble } from "hooks/useTeachingBubble";
|
||||
import ko from "knockout";
|
||||
import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
||||
import React, { MutableRefObject, Suspense, useEffect, useRef, useState } from "react";
|
||||
import errorQuery from "../../../images/error_no_outline.svg";
|
||||
import warningIconSvg from "../../../images/warning.svg";
|
||||
import { useObservable } from "../../hooks/useObservable";
|
||||
import { ReactTabKind, useTabs } from "../../hooks/useTabs";
|
||||
import TabsBase from "./TabsBase";
|
||||
|
||||
// Lazy-loaded tab components (code-split by API type)
|
||||
const QueryCopilotTab = React.lazy(() =>
|
||||
import(/* webpackChunkName: "QueryCopilotTab" */ "Explorer/QueryCopilot/QueryCopilotTab").then((m) => ({
|
||||
default: m.QueryCopilotTab,
|
||||
})),
|
||||
);
|
||||
const FabricHomeScreen = React.lazy(() =>
|
||||
import(/* webpackChunkName: "FabricHomeScreen" */ "Explorer/SplashScreen/FabricHome").then((m) => ({
|
||||
default: m.FabricHomeScreen,
|
||||
})),
|
||||
);
|
||||
const PostgresConnectTab = React.lazy(() =>
|
||||
import(/* webpackChunkName: "PostgresConnectTab" */ "Explorer/Tabs/PostgresConnectTab").then((m) => ({
|
||||
default: m.PostgresConnectTab,
|
||||
})),
|
||||
);
|
||||
const VcoreMongoConnectTab = React.lazy(() =>
|
||||
import(/* webpackChunkName: "VcoreMongoConnectTab" */ "Explorer/Tabs/VCoreMongoConnectTab").then((m) => ({
|
||||
default: m.VcoreMongoConnectTab,
|
||||
})),
|
||||
);
|
||||
const VcoreMongoQuickstartTab = React.lazy(() =>
|
||||
import(/* webpackChunkName: "VcoreMongoQuickstartTab" */ "Explorer/Tabs/VCoreMongoQuickstartTab").then((m) => ({
|
||||
default: m.VcoreMongoQuickstartTab,
|
||||
})),
|
||||
);
|
||||
|
||||
type Tab = TabsBase | (TabsBase & { render: () => JSX.Element });
|
||||
|
||||
interface TabsProps {
|
||||
@@ -302,30 +324,33 @@ const isQueryErrorThrown = (tab?: Tab, tabKind?: ReactTabKind): boolean => {
|
||||
};
|
||||
|
||||
const getReactTabContent = (activeReactTab: ReactTabKind, explorer: Explorer): JSX.Element => {
|
||||
switch (activeReactTab) {
|
||||
case ReactTabKind.Connect:
|
||||
return userContext.apiType === "VCoreMongo" ? (
|
||||
<VcoreMongoConnectTab />
|
||||
) : userContext.apiType === "Postgres" ? (
|
||||
<PostgresConnectTab />
|
||||
) : (
|
||||
<ConnectTab />
|
||||
);
|
||||
case ReactTabKind.Home:
|
||||
if (isFabricNative()) {
|
||||
return <FabricHomeScreen explorer={explorer} />;
|
||||
} else {
|
||||
return <SplashScreen explorer={explorer} />;
|
||||
}
|
||||
case ReactTabKind.Quickstart:
|
||||
return userContext.apiType === "VCoreMongo" ? (
|
||||
<VcoreMongoQuickstartTab explorer={explorer} />
|
||||
) : (
|
||||
<QuickstartTab explorer={explorer} />
|
||||
);
|
||||
case ReactTabKind.QueryCopilot:
|
||||
return <QueryCopilotTab explorer={explorer} />;
|
||||
default:
|
||||
throw new Error(`Unsupported tab kind ${ReactTabKind[activeReactTab]}`);
|
||||
}
|
||||
const content = (() => {
|
||||
switch (activeReactTab) {
|
||||
case ReactTabKind.Connect:
|
||||
return userContext.apiType === "VCoreMongo" ? (
|
||||
<VcoreMongoConnectTab />
|
||||
) : userContext.apiType === "Postgres" ? (
|
||||
<PostgresConnectTab />
|
||||
) : (
|
||||
<ConnectTab />
|
||||
);
|
||||
case ReactTabKind.Home:
|
||||
if (isFabricNative()) {
|
||||
return <FabricHomeScreen explorer={explorer} />;
|
||||
} else {
|
||||
return <SplashScreen explorer={explorer} />;
|
||||
}
|
||||
case ReactTabKind.Quickstart:
|
||||
return userContext.apiType === "VCoreMongo" ? (
|
||||
<VcoreMongoQuickstartTab explorer={explorer} />
|
||||
) : (
|
||||
<QuickstartTab explorer={explorer} />
|
||||
);
|
||||
case ReactTabKind.QueryCopilot:
|
||||
return <QueryCopilotTab explorer={explorer} />;
|
||||
default:
|
||||
throw new Error(`Unsupported tab kind ${ReactTabKind[activeReactTab]}`);
|
||||
}
|
||||
})();
|
||||
return <Suspense fallback={<Spinner size={SpinnerSize.large} />}>{content}</Suspense>;
|
||||
};
|
||||
|
||||
@@ -34,7 +34,7 @@ import Explorer from "../Explorer";
|
||||
import { useCommandBar } from "../Menus/CommandBar/CommandBarComponentAdapter";
|
||||
import { CassandraAPIDataClient, CassandraTableKey, CassandraTableKeys } from "../Tables/TableDataClient";
|
||||
import ConflictsTab from "../Tabs/ConflictsTab";
|
||||
import GraphTab from "../Tabs/GraphTab";
|
||||
import type GraphTab from "../Tabs/GraphTab";
|
||||
import { NewMongoQueryTab } from "../Tabs/MongoQueryTab/MongoQueryTab";
|
||||
import { NewMongoShellTab } from "../Tabs/MongoShellTab/MongoShellTab";
|
||||
import { NewQueryTab } from "../Tabs/QueryTab/QueryTab";
|
||||
@@ -450,7 +450,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
}
|
||||
}
|
||||
|
||||
public onGraphDocumentsClick() {
|
||||
public async onGraphDocumentsClick() {
|
||||
useSelectedNode.getState().setSelectedNode(this);
|
||||
this.selectedSubnodeKind(ViewModels.CollectionTabKind.Graph);
|
||||
TelemetryProcessor.trace(Action.SelectItem, ActionModifiers.Mark, {
|
||||
@@ -483,7 +483,8 @@ export default class Collection implements ViewModels.Collection {
|
||||
tabTitle: title,
|
||||
});
|
||||
|
||||
graphTab = new GraphTab({
|
||||
const { default: GraphTabModule } = await import(/* webpackChunkName: "GraphTab" */ "../Tabs/GraphTab");
|
||||
graphTab = new GraphTabModule({
|
||||
account: userContext.databaseAccount,
|
||||
tabKind: ViewModels.CollectionTabKind.Graph,
|
||||
node: this,
|
||||
@@ -727,7 +728,7 @@ export default class Collection implements ViewModels.Collection {
|
||||
useTabs.getState().activateNewTab(newMongoQueryTab);
|
||||
}
|
||||
|
||||
public onNewGraphClick() {
|
||||
public async onNewGraphClick() {
|
||||
const id: number = useTabs.getState().getTabs(ViewModels.CollectionTabKind.Graph).length + 1;
|
||||
const title: string = "Graph Query " + id;
|
||||
|
||||
@@ -739,7 +740,8 @@ export default class Collection implements ViewModels.Collection {
|
||||
tabTitle: title,
|
||||
});
|
||||
|
||||
const graphTab: GraphTab = new GraphTab({
|
||||
const { default: GraphTabModule } = await import(/* webpackChunkName: "GraphTab" */ "../Tabs/GraphTab");
|
||||
const graphTab: GraphTab = new GraphTabModule({
|
||||
account: userContext.databaseAccount,
|
||||
tabKind: ViewModels.CollectionTabKind.Graph,
|
||||
node: this,
|
||||
|
||||
+54
-19
@@ -5,27 +5,14 @@ import "./ReactDevTools";
|
||||
import { initializeIcons, loadTheme, useTheme } from "@fluentui/react";
|
||||
import { FluentProvider, makeStyles, webDarkTheme, webLightTheme } from "@fluentui/react-components";
|
||||
import { Platform } from "ConfigContext";
|
||||
import ContainerCopyPanel from "Explorer/ContainerCopy/ContainerCopyPanel";
|
||||
import Explorer from "Explorer/Explorer";
|
||||
import { QuickstartCarousel } from "Explorer/Quickstart/QuickstartCarousel";
|
||||
import { MongoQuickstartTutorial } from "Explorer/Quickstart/Tutorials/MongoQuickstartTutorial";
|
||||
import { SQLQuickstartTutorial } from "Explorer/Quickstart/Tutorials/SQLQuickstartTutorial";
|
||||
import { userContext } from "UserContext";
|
||||
import "allotment/dist/style.css";
|
||||
import "bootstrap/dist/css/bootstrap.css";
|
||||
import { useCarousel } from "hooks/useCarousel";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import "../externals/jquery-ui.min.css";
|
||||
import "../externals/jquery-ui.min.js";
|
||||
import "../externals/jquery-ui.structure.min.css";
|
||||
import "../externals/jquery-ui.theme.min.css";
|
||||
import "../externals/jquery.dataTables.min.css";
|
||||
import "../externals/jquery.typeahead.min.css";
|
||||
import "../externals/jquery.typeahead.min.js";
|
||||
// Image Dependencies
|
||||
import { SidePanel } from "Explorer/Panes/PanelContainerComponent";
|
||||
import { QueryCopilotCarousel } from "Explorer/QueryCopilot/CopilotCarousel";
|
||||
import { SidebarContainer } from "Explorer/Sidebar";
|
||||
import { KeyboardShortcutRoot } from "KeyboardShortcuts";
|
||||
import "allotment/dist/style.css";
|
||||
@@ -72,6 +59,50 @@ import { useKnockoutExplorer } from "./hooks/useKnockoutExplorer";
|
||||
import { useThemeStore } from "./hooks/useTheme";
|
||||
import "./less/DarkModeMenus.less";
|
||||
import "./less/ThemeSystem.less";
|
||||
// Lazy-loaded components (code-split into separate chunks)
|
||||
const ContainerCopyPanel = React.lazy(
|
||||
() => import(/* webpackChunkName: "ContainerCopyPanel" */ "Explorer/ContainerCopy/ContainerCopyPanel"),
|
||||
);
|
||||
const QuickstartCarousel = React.lazy(() =>
|
||||
import(/* webpackChunkName: "QuickstartCarousel" */ "Explorer/Quickstart/QuickstartCarousel").then((m) => ({
|
||||
default: m.QuickstartCarousel,
|
||||
})),
|
||||
);
|
||||
const SQLQuickstartTutorial = React.lazy(() =>
|
||||
import(/* webpackChunkName: "SQLQuickstartTutorial" */ "Explorer/Quickstart/Tutorials/SQLQuickstartTutorial").then(
|
||||
(m) => ({ default: m.SQLQuickstartTutorial }),
|
||||
),
|
||||
);
|
||||
const MongoQuickstartTutorial = React.lazy(() =>
|
||||
import(
|
||||
/* webpackChunkName: "MongoQuickstartTutorial" */ "Explorer/Quickstart/Tutorials/MongoQuickstartTutorial"
|
||||
).then((m) => ({ default: m.MongoQuickstartTutorial })),
|
||||
);
|
||||
const QueryCopilotCarousel = React.lazy(() =>
|
||||
import(/* webpackChunkName: "QueryCopilotCarousel" */ "Explorer/QueryCopilot/CopilotCarousel").then((m) => ({
|
||||
default: m.QueryCopilotCarousel,
|
||||
})),
|
||||
);
|
||||
|
||||
// Defer loading legacy jQuery/Bootstrap CSS and JS — they are needed by Tables features, not on initial render
|
||||
const loadLegacyDependencies = () => {
|
||||
// @ts-expect-error — side-effect-only imports handled by webpack, not real TS/ES modules
|
||||
import(/* webpackChunkName: "legacy-styles" */ "bootstrap/dist/css/bootstrap.css");
|
||||
// @ts-expect-error — webpack handles CSS imports
|
||||
import(/* webpackChunkName: "legacy-styles" */ "../externals/jquery-ui.min.css");
|
||||
// @ts-expect-error — webpack handles JS side-effect imports
|
||||
import(/* webpackChunkName: "legacy-scripts" */ "../externals/jquery-ui.min.js");
|
||||
// @ts-expect-error — webpack handles CSS imports
|
||||
import(/* webpackChunkName: "legacy-styles" */ "../externals/jquery-ui.structure.min.css");
|
||||
// @ts-expect-error — webpack handles CSS imports
|
||||
import(/* webpackChunkName: "legacy-styles" */ "../externals/jquery-ui.theme.min.css");
|
||||
// @ts-expect-error — webpack handles CSS imports
|
||||
import(/* webpackChunkName: "legacy-styles" */ "../externals/jquery.dataTables.min.css");
|
||||
// @ts-expect-error — webpack handles CSS imports
|
||||
import(/* webpackChunkName: "legacy-styles" */ "../externals/jquery.typeahead.min.css");
|
||||
import(/* webpackChunkName: "legacy-scripts" */ "../externals/jquery.typeahead.min.js");
|
||||
};
|
||||
|
||||
// Initialize icons before React is loaded
|
||||
initializeIcons(undefined, { disableWarnings: true });
|
||||
|
||||
@@ -98,6 +129,8 @@ const App = (): JSX.Element => {
|
||||
import("../less/documentDBFabric.less");
|
||||
}
|
||||
StyleConstants.updateStyles();
|
||||
// Load legacy jQuery/Bootstrap dependencies after initial render
|
||||
loadLegacyDependencies();
|
||||
}, [config?.platform]);
|
||||
|
||||
const explorer = useKnockoutExplorer(config?.platform);
|
||||
@@ -131,11 +164,11 @@ const App = (): JSX.Element => {
|
||||
<KeyboardShortcutRoot>
|
||||
<div className="flexContainer" aria-hidden="false">
|
||||
{userContext.features.enableContainerCopy && userContext.apiType === "SQL" ? (
|
||||
<>
|
||||
<React.Suspense fallback={null}>
|
||||
<ContainerCopyPanel explorer={explorer} />
|
||||
<SidePanel />
|
||||
<Dialog />
|
||||
</>
|
||||
</React.Suspense>
|
||||
) : (
|
||||
<DivExplorer explorer={explorer} />
|
||||
)}
|
||||
@@ -191,10 +224,12 @@ const DivExplorer: React.FC<{ explorer: Explorer }> = ({ explorer }) => {
|
||||
</div>
|
||||
<SidePanel />
|
||||
<Dialog />
|
||||
{<QuickstartCarousel isOpen={isCarouselOpen} />}
|
||||
{<SQLQuickstartTutorial />}
|
||||
{<MongoQuickstartTutorial />}
|
||||
{<QueryCopilotCarousel isOpen={isCopilotCarouselOpen} explorer={explorer} />}
|
||||
<React.Suspense fallback={null}>
|
||||
{<QuickstartCarousel isOpen={isCarouselOpen} />}
|
||||
{<SQLQuickstartTutorial />}
|
||||
{<MongoQuickstartTutorial />}
|
||||
{<QueryCopilotCarousel isOpen={isCopilotCarouselOpen} explorer={explorer} />}
|
||||
</React.Suspense>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
+25
-1
@@ -123,7 +123,7 @@ module.exports = function (_env = {}, argv = {}) {
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "explorer.html",
|
||||
template: "src/explorer.html",
|
||||
chunks: ["main"],
|
||||
chunks: ["main", "vendor", "vendor-fluentui", "vendor-nteract"],
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
filename: "terminal.html",
|
||||
@@ -262,6 +262,30 @@ module.exports = function (_env = {}, argv = {}) {
|
||||
},
|
||||
}),
|
||||
],
|
||||
splitChunks: {
|
||||
chunks: "all",
|
||||
maxInitialRequests: 10,
|
||||
cacheGroups: {
|
||||
fluentui: {
|
||||
test: /[\\/]node_modules[\\/]@fluentui[\\/]/,
|
||||
name: "vendor-fluentui",
|
||||
chunks: "all",
|
||||
priority: 30,
|
||||
},
|
||||
nteract: {
|
||||
test: /[\\/]node_modules[\\/]@nteract[\\/]/,
|
||||
name: "vendor-nteract",
|
||||
chunks: "all",
|
||||
priority: 30,
|
||||
},
|
||||
vendor: {
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
name: "vendor",
|
||||
chunks: "all",
|
||||
priority: 10,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
watch: false,
|
||||
// Hack since it is hard to disable watch entirely with webpack dev server https://github.com/webpack/webpack-dev-server/issues/1251#issuecomment-654240734
|
||||
|
||||
Reference in New Issue
Block a user