fix(FE): AppRoutes is refactored (#260)

* react-app-env.d.ts is moved to the typings

* webpack config for development and production is updated

* extra browser router component is removed

* loable component is made

* spinner component is updated

* route are updated

* routes are imported is Loadable fashion with chunkName

* AppRoute is updated

* AppWrapper is changed to AppRouter

* merge conflits are resolved

* Loadable component is updated

Co-authored-by: Ankit Nayan <ankit@signoz.io>
This commit is contained in:
palash-signoz 2021-08-23 11:38:25 +05:30 committed by GitHub
parent f394f72bfb
commit 9008d19a7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 242 additions and 153 deletions

View File

@ -0,0 +1,43 @@
import React, { Suspense } from "react";
import ROUTES from "constants/routes";
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
import Spinner from "components/Spinner";
import NotFound from "components/NotFound";
import { IS_LOGGED_IN } from "constants/auth";
import AppLayout from "modules/AppLayout";
import { RouteProvider } from "modules/RouteProvider";
import routes from "./routes";
const App = () => (
<BrowserRouter basename="/">
<RouteProvider>
<AppLayout>
<Suspense fallback={<Spinner size="large" tip="Loading..." />}>
<Switch>
{routes.map(({ path, component, exact }) => {
return <Route exact={exact} path={path} component={component} />;
})}
{/* This logic should be moved to app layout */}
<Route
path="/"
exact
render={() => {
return localStorage.getItem(IS_LOGGED_IN) === "yes" ? (
<Redirect to={ROUTES.APPLICATION} />
) : (
<Redirect to={ROUTES.SIGN_UP} />
);
}}
/>
<Route path="*" component={NotFound} />
</Switch>
</Suspense>
</AppLayout>
</RouteProvider>
</BrowserRouter>
);
export default App;

View File

@ -0,0 +1,70 @@
import {
ServiceMetricsPage,
ServiceMapPage,
TraceDetailPage,
TraceGraphPage,
UsageExplorerPage,
ServicesTablePage,
SignupPage,
SettingsPage,
InstrumentationPage,
} from "pages";
import ROUTES from "constants/routes";
import { RouteProps } from "react-router-dom";
const routes: AppRoutes[] = [
{
component: SignupPage,
path: ROUTES.SIGN_UP,
exact: true,
},
{
component: ServicesTablePage,
path: ROUTES.APPLICATION,
exact: true,
},
{
path: ROUTES.SERVICE_METRICS,
exact: true,
component: ServiceMetricsPage,
},
{
path: ROUTES.SERVICE_MAP,
component: ServiceMapPage,
exact: true,
},
{
path: ROUTES.TRACE_GRAPH,
exact: true,
component: TraceGraphPage,
},
{
path: ROUTES.SETTINGS,
exact: true,
component: SettingsPage,
},
{
path: ROUTES.USAGE_EXPLORER,
exact: true,
component: UsageExplorerPage,
},
{
path: ROUTES.INSTRUMENTATION,
exact: true,
component: InstrumentationPage,
},
{
path: ROUTES.TRACES,
exact: true,
component: TraceDetailPage,
},
];
interface AppRoutes {
component: RouteProps["component"];
path: RouteProps["path"];
exact: RouteProps["exact"];
isPrivate?: boolean;
}
export default routes;

View File

@ -0,0 +1,17 @@
import { lazy, ComponentType } from "react";
function Loadable(importPath: {
(): LoadableProps;
}): React.LazyExoticComponent<LazyComponent> {
const LazyComponent = lazy(() => importPath());
return LazyComponent;
}
type LazyComponent = ComponentType<Record<string, unknown>>;
type LoadableProps = Promise<{
default: LazyComponent;
}>;
export default Loadable;

View File

@ -1,42 +0,0 @@
import React from 'react';
import { Spin } from 'antd';
import styled from "styled-components";
import { LoadingOutlined } from '@ant-design/icons';
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
const SpinerStyle = styled.div`
position: fixed;
z-index: 999;
height: 4em;
// width: 4em;
overflow: visible;
margin: auto;
top: 0;
left: 50%;
bottom: 0;
right: 0;
`;
export const CustomSpinner = ({
size,
tip,
}:{
size:string,
tip:string,
})=>{
return(
<>
<SpinerStyle>
<Spin size={size} tip={tip} indicator={antIcon}/>
</SpinerStyle>
</>
)
}
export const DefaultSpinner = ()=>{
return(
<>
<Spin indicator={antIcon}/>
</>
)
}

View File

@ -0,0 +1,19 @@
import React from "react";
import { Spin, SpinProps } from "antd";
import { LoadingOutlined } from "@ant-design/icons";
import { SpinerStyle } from "./styles";
const Spinner = ({ size, tip, height }: SpinnerProps): JSX.Element => (
<SpinerStyle height={height}>
<Spin spinning size={size} tip={tip} indicator={<LoadingOutlined spin />} />
</SpinerStyle>
);
interface SpinnerProps {
size?: SpinProps["size"];
tip?: SpinProps["tip"];
height?: React.CSSProperties["height"];
}
export default Spinner;

View File

@ -0,0 +1,16 @@
import React from "react";
import styled from "styled-components";
interface Props {
height: React.CSSProperties["height"];
}
export const SpinerStyle = styled.div<Props>`
z-index: 999;
overflow: visible;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
height: ${({ height = "100vh" }) => height};
`;

View File

@ -3,18 +3,15 @@ import ReactDOM from "react-dom";
import { Provider } from "react-redux"; import { Provider } from "react-redux";
import { ThemeSwitcherProvider } from "react-css-theme-switcher"; import { ThemeSwitcherProvider } from "react-css-theme-switcher";
import store from "store"; import store from "store";
import AppWrapper from "modules/AppWrapper"; import AppRoutes from "AppRoutes";
import "assets/index.css"; import "assets/index.css";
import { BrowserRouter as Router } from "react-router-dom";
import themes from "themes"; import themes from "themes";
ReactDOM.render( ReactDOM.render(
<Provider store={store}> <Provider store={store}>
<React.StrictMode> <React.StrictMode>
<ThemeSwitcherProvider themeMap={themes} defaultTheme="dark"> <ThemeSwitcherProvider themeMap={themes} defaultTheme="dark">
<Router basename="/"> <AppRoutes />
<AppWrapper />
</Router>
</ThemeSwitcherProvider> </ThemeSwitcherProvider>
</React.StrictMode> </React.StrictMode>
</Provider>, </Provider>,

View File

@ -1,70 +0,0 @@
import React, { Suspense } from "react";
import { useThemeSwitcher } from "react-css-theme-switcher";
import ROUTES from "constants/routes";
import { IS_LOGGED_IN } from "constants/auth";
import { BrowserRouter, Route, Switch, Redirect } from "react-router-dom";
import { CustomSpinner } from "components/Spiner";
import BaseLayout from "./BaseLayout";
import {
ServiceMetrics,
ServiceMap,
TraceDetail,
TraceGraph,
UsageExplorer,
ServicesTable,
Signup,
SettingsPage,
InstrumentationPage,
} from "pages";
import { RouteProvider } from "./RouteProvider";
import NotFound from "components/NotFound";
const App = () => {
const { status } = useThemeSwitcher();
if (status === "loading") {
return <CustomSpinner size="large" tip="Loading..." />;
}
return (
<BrowserRouter>
<RouteProvider>
<BaseLayout>
<Suspense fallback={<CustomSpinner size="large" tip="Loading..." />}>
<Switch>
<Route path={ROUTES.SIGN_UP} exact component={Signup} />
<Route path={ROUTES.APPLICATION} exact component={ServicesTable} />
<Route path={ROUTES.SERVICE_METRICS} exact component={ServiceMetrics} />
<Route path={ROUTES.SERVICE_MAP} exact component={ServiceMap} />
<Route path={ROUTES.TRACES} exact component={TraceDetail} />
<Route path={ROUTES.TRACE_GRAPH} exact component={TraceGraph} />
<Route path={ROUTES.SETTINGS} exact component={SettingsPage} />
<Route
path={ROUTES.INSTRUMENTATION}
exact
component={InstrumentationPage}
/>
<Route path={ROUTES.USAGE_EXPLORER} exact component={UsageExplorer} />
<Route
path="/"
exact
render={() => {
return localStorage.getItem(IS_LOGGED_IN) === "yes" ? (
<Redirect to={ROUTES.APPLICATION} />
) : (
<Redirect to={ROUTES.SIGN_UP} />
);
}}
/>
<Route path="*" exact component={NotFound} />
</Switch>
</Suspense>
</BaseLayout>
</RouteProvider>
</BrowserRouter>
);
};
export default App;

View File

@ -3,13 +3,13 @@ import { NavLink } from "react-router-dom";
import { Button, Space, Table } from "antd"; import { Button, Space, Table } from "antd";
import styled from "styled-components"; import styled from "styled-components";
import { connect } from "react-redux"; import { connect } from "react-redux";
import Spinner from "components/Spinner";
import { SKIP_ONBOARDING } from "constants/onboarding"; import { SKIP_ONBOARDING } from "constants/onboarding";
import ROUTES from "constants/routes"; import ROUTES from "constants/routes";
import { getServicesList, GlobalTime } from "store/actions"; import { getServicesList, GlobalTime } from "store/actions";
import { servicesListItem } from "store/actions/MetricsActions"; import { servicesListItem } from "store/actions/MetricsActions";
import { StoreState } from "store/reducers"; import { StoreState } from "store/reducers";
import { CustomModal } from "components/Modal"; import { CustomModal } from "components/Modal";
import { CustomSpinner, DefaultSpinner } from "components/Spiner";
interface ServicesTableProps { interface ServicesTableProps {
servicesList: servicesListItem[]; servicesList: servicesListItem[];
@ -124,7 +124,7 @@ const _ServicesTable = (props: ServicesTableProps) => {
}, [props.servicesList, errorObject]); }, [props.servicesList, errorObject]);
if (!initialDataFetch) { if (!initialDataFetch) {
return <CustomSpinner size="large" tip="Fetching data..." />; return <Spinner height="90vh" size="large" tip="Fetching data..." />;
} }
if (refetchFromBackend && !skipOnboarding) { if (refetchFromBackend && !skipOnboarding) {
@ -150,7 +150,7 @@ const _ServicesTable = (props: ServicesTableProps) => {
allowFullScreen allowFullScreen
></iframe> ></iframe>
<div style={{ margin: "20px 0" }}> <div style={{ margin: "20px 0" }}>
<DefaultSpinner /> <Spinner />
</div> </div>
<div> <div>
No instrumentation data. No instrumentation data.

View File

@ -1,6 +1,6 @@
import React, { useEffect, useRef } from "react"; import React, { useEffect, useRef } from "react";
import { connect } from "react-redux"; import { connect } from "react-redux";
import { RouteComponentProps } from "react-router-dom"; import { RouteComponentProps, withRouter } from "react-router-dom";
import { import {
GlobalTime, GlobalTime,
serviceMapStore, serviceMapStore,
@ -13,8 +13,8 @@ import { StoreState } from "store/reducers";
import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils"; import { getZoomPx, getGraphData, getTooltip, transformLabel } from "./utils";
import SelectService from "./SelectService"; import SelectService from "./SelectService";
import { ForceGraph2D } from "react-force-graph"; import { ForceGraph2D } from "react-force-graph";
import Spinner from "components/Spinner";
import { useRoute } from "modules/RouteProvider"; import { useRoute } from "modules/RouteProvider";
import { CustomSpinner } from "components/Spiner";
const Container = styled.div` const Container = styled.div`
.force-graph-container .graph-tooltip { .force-graph-container .graph-tooltip {
@ -78,7 +78,7 @@ const ServiceMap = (props: ServiceMapProps) => {
fgRef.current && fgRef.current.d3Force("charge").strength(-400); fgRef.current && fgRef.current.d3Force("charge").strength(-400);
}); });
if (!serviceMap.items.length || !serviceMap.services.length) { if (!serviceMap.items.length || !serviceMap.services.length) {
return <CustomSpinner size="large" tip="Loading..." />; return <Spinner size="large" tip="Loading..." />;
} }
const zoomToService = (value: string) => { const zoomToService = (value: string) => {
@ -150,7 +150,9 @@ const mapStateToProps = (
}; };
}; };
export default connect(mapStateToProps, { export default withRouter(
getServiceMapItems: getServiceMapItems, connect(mapStateToProps, {
getDetailedServiceMapItems: getDetailedServiceMapItems, getServiceMapItems: getServiceMapItems,
})(ServiceMap); getDetailedServiceMapItems: getDetailedServiceMapItems,
})(ServiceMap),
);

View File

@ -1,28 +1,61 @@
import React from "react"; import Loadable from "./components/Loadable";
export const ServiceMetrics = React.lazy( export const ServiceMetricsPage = Loadable(
() => import("modules/Metrics/ServiceMetricsDef"), () =>
); import(
export const ServiceMap = React.lazy( /* webpackChunkName: "ServiceMetricsPage" */ "modules/Metrics/ServiceMetricsDef"
() => import("modules/Servicemap/ServiceMap"), ),
);
export const TraceDetail = React.lazy(
() => import("modules/Traces/TraceDetail"),
);
export const TraceGraph = React.lazy(
() => import("modules/Traces/TraceGraphDef"),
);
export const UsageExplorer = React.lazy(
() => import("modules/Usage/UsageExplorerDef"),
);
export const ServicesTable = React.lazy(
() => import("modules/Metrics/ServicesTableDef"),
);
export const Signup = React.lazy(() => import("modules/Auth/Signup"));
export const SettingsPage = React.lazy(
() => import("modules/Settings/settingsPage"),
); );
export const InstrumentationPage = React.lazy( export const ServiceMapPage = Loadable(
() => import("modules/add-instrumentation/instrumentationPage"), () =>
import(
/* webpackChunkName: "ServiceMapPage" */ "modules/Servicemap/ServiceMap"
),
);
export const TraceDetailPage = Loadable(
() =>
import(
/* webpackChunkName: "TraceDetailPage" */ "modules/Traces/TraceDetail"
),
);
export const TraceGraphPage = Loadable(
() =>
import(
/* webpackChunkName: "TraceGraphPage" */ "modules/Traces/TraceGraphDef"
),
);
export const UsageExplorerPage = Loadable(
() =>
import(
/* webpackChunkName: "UsageExplorerPage" */ "modules/Usage/UsageExplorerDef"
),
);
export const ServicesTablePage = Loadable(
() =>
import(
/* webpackChunkName: "ServicesTablePage" */ "modules/Metrics/ServicesTableDef"
),
);
export const SignupPage = Loadable(
() => import(/* webpackChunkName: "SignupPage" */ "modules/Auth/Signup"),
);
export const SettingsPage = Loadable(
() =>
import(
/* webpackChunkName: "SettingsPage" */ "modules/Settings/settingsPage"
),
);
export const InstrumentationPage = Loadable(
() =>
import(
/* webpackChunkName: "InstrumentationPage" */ "modules/add-instrumentation/instrumentationPage"
),
); );

View File

@ -29,7 +29,9 @@ module.exports = {
port: portFinderSync.getPort(3000), port: portFinderSync.getPort(3000),
}, },
output: { output: {
filename: "js/bundle.[chunkhash].min.js", filename: ({ chunk: { name, hash } }) => {
return `js/${name}-${hash}.js`;
},
path: resolve(__dirname, "./build"), path: resolve(__dirname, "./build"),
publicPath: "/", publicPath: "/",
}, },

View File

@ -11,7 +11,9 @@ module.exports = {
devtool: "source-map", devtool: "source-map",
entry: resolve(__dirname, "./src/index.tsx"), entry: resolve(__dirname, "./src/index.tsx"),
output: { output: {
filename: "js/bundle.[chunkhash].min.js", filename: ({ chunk: { name, hash } }) => {
return `js/${name}-${hash}.js`;
},
path: resolve(__dirname, "./build"), path: resolve(__dirname, "./build"),
publicPath: "/", publicPath: "/",
}, },