Route and Components
This section describes routes and components relations.
Page structure
For all application routes, you can specify the list of components names that will be rendered on this route. This list can contain only components keys, whereas according React components will be automatically resolved from special service - ComponentRegistry
.
List of possible components:
pageComponent
- component with page contentnestedLayoutComponent
- component with page layouterrorBoundaryComponent
- component with page error boundarylayoutComponent
- component with root layout
Page structure with all components looks like this, simplified:
const Root = () => (
<LayoutComponent>
<Header />
<NestedLayoutComponent>
<ErrorBoundaryComponent>
<PageComponent />
</ErrorBoundaryComponent>
</NestedLayoutComponent>
<Footer />
</LayoutComponent>
);
File-System Routing
For FS routes, route with list of components will be created automatically, and all components will be automatically registered in ComponentRegistry
.
For example, from this file structure:
src
└── routes
├── index.tsx
├── _layout.tsx
└── _error.tsx
This route will be created:
[{
path: '/',
config: {
pageComponent: '@/routes/index',
nestedLayoutComponent: '@/routes/index__layout',
errorBoundaryComponent: '@/routes/index__errorBoundary',
},
}];
Manually created routes
For manually created routes, you need to use pages
directory, all components from this directory will be automatically registered in ComponentRegistry
.
Example file structure:
src
└── pages
├── main.tsx
├── main-layout.tsx
└── main-error.tsx
And you can create this route with all of this components:
import { SpaRouterModule } from '@tramvai/modules-router';
createApp({
modules: [
SpaRouterModule.forRoot([{
name: 'main',
path: '/',
config: {
pageComponent: '@/pages/main',
nestedLayoutComponent: '@/pages/main-layout',
errorBoundaryComponent: '@/pages/main-error',
},
}]),
],
});
Default components
For all components can be specified default component, e.g. that keys will be used if component with specified in route config key is not found in ComponentRegistry
:
const mapping = {
pageComponent: 'pageDefault',
nestedLayoutComponent: 'nestedLayoutDefault',
errorBoundaryComponent: 'errorBoundaryDefault',
layoutComponent: 'layoutDefault',
}
Default Root Layout already provided by token DEFAULT_LAYOUT_COMPONENT
, this is default application layout and it is not recommended to change it.
Default Page Error Boundary can be provided by token DEFAULT_ERROR_BOUNDARY_COMPONENT
.
Default Page Nested Layout is not supported for FS routes or pages and is not necessary, because Root LAYOUT_OPTIONS
is more powerful mechanism - wrappers.page
is complete alternative for nested layout in page components hierarchy.
Default Page Component is not supported for FS routes or pages, only for legacy bundles.
Bundles (legacy)
Bundles is legacy feature, and it is recommended to use File-System routing in new projects.
For bundles situation is more complicated, because bundles can group several components, and different routes can use the same bundle. Also, it means that for bundles additional level of default components will be used.
Important default for routes if bundles is used, is default bundle and page component keys:
const routeConfig = {
bundle: 'mainDefault',
pageComponent: 'pageDefault',
};
It means that all routes without FS routing will use mainDefault
bundle, and get pageDefault
page component from this bundle. Example of this default bundle:
import { createBundle } from '@tramvai/core';
import { lazy } from '@tramvai/react';
export const mainDefault = createBundle({
name: 'mainDefault',
components: {
pageDefault: lazy(() => import('../components/main-page')),
},
});
And for this simple route, components/main-page.tsx
page component will be rendered:
import { SpaRouterModule } from '@tramvai/modules-router';
createApp({
modules: [
SpaRouterModule.forRoot([{
name: 'main',
path: '/',
}]),
],
bundles: {
mainDefault: () => import(/* webpackChunkName: "mainDefault" */ './bundles/mainDefault'),
},
});
All other default components will applied to route with this bundle, e.g.:
import { createBundle } from '@tramvai/core';
import { lazy } from '@tramvai/react';
export const mainDefault = createBundle({
name: 'mainDefault',
components: {
pageDefault: lazy(() => import('../components/main-page')),
nestedLayoutDefault: lazy(() => import('../components/main-layout')),
errorBoundaryDefault: lazy(() => import('../components/main-error')),
layoutDefault: lazy(() => import('../components/layout')),
},
});
Defaults from Defaults components section also will be applied, but with lower priority.
In summary:
- If
pageComponent
,layoutComponent
,nestedLayoutComponent
orerrorBoundaryComponent
properties is specified in route config, they values will be used as components keys - Otherwise,
pageDefault
,layoutDefault
,nestedLayoutDefault
orerrorBoundaryDefault
will be used as components keys - Then, if current bundle components has component with this key, it will be used
- Otherwise,
tramvai
will try to find this keys in default components - Only for Page Component, if it is not found anywhere, 500 error will be thrown