kingsquare-nextjs-routing
This package allows custom dynamic routing for nextjs.
Keep in mind this package is tailored to meet Kingsquare's needs and may not fit your project perfectly.
Basic usage
The tool requires three properties: PageNodes, a list of Controllers and the nextjs "DocumentContext".
The most basic usage is as follows:
../pages/index.tsx import KNR from "kingsquare-nextjs-routing"; ... const Page = (pageProps) => { const { props, Component } = pageProps; return <Component {...props} />; }; ... Page.getInitialProps = async props => { return await KNR({ pageNodes, controllers, ...props }); };
With this tool the /pages folder will be used purely for routing.
In order to pass all requests through this tool you two pages in the /pages folder.
The first one is shown above, the index.tsx
, this will catch all the calls to the home pages.
As second you need a page that can catch all requests, [...alias].tsx
. The [...alias] page should look something like this:
import Page from "./index"; export default Page;
Because the /pages folder will only be used for routing all your regular pages should be moved to a different folder in your project.
!!! The _app, _error, _document (, etc.) files should remain in the /pages folder. !!!
GetInitialProps
The KNR tool will call the getInitialProps method of the Component that should be returned. The KNR tool returns the response of this method call.
Return values
As mentioned above, the KNR
tool returns the properties of the Component that should be returned along the Component itself. The return type looks like this:
{ Component: NextPage; props?: { [key: string]: any; }; }
Keep in mind that props
can be undefined.
Controllers
As shown in the index.tsx example, the KNR tool requires a 'controllers' property.
This is a object of all the pages in your site. The typescript definition of the controllers is:
{ home: NextPage, alias: NextPage, 404: NextPage, redirect: NextPage, [key: string]: NextPage, }
As shown above, the list requires at least a controller for the homepage, the 'default' (alias) page, the 404 and the redirect (used in case the window isn't defined and a regular redirect isn't possible).
The type NextPage
is the type of all pages used in nextjs. Creating this list looks kinda like this:
import HomePage from "../myPages"; import AliasPage from "../myPages/[alias]"; import ErrorPage from "./_error"; import RedirectPage from "../myPages/redirect"; import FaqPage from "../myPages/faq"; const controllers = { home: HomePage, alias: AliasPage, 404: ErrorPage, redirect: RedirectPage, faq: FaqPage, };
PageNodes
The pageNodes act like your routing scheme. Here our can define which paths can be hit and what they will return. The typescript definition of the pageNodes is as follows:
{ controller?: string; redirectUrl?: string; url: string; }
Url
This is used to determine which pageNode corresponds to the path that is being called. Here you only should define the first part of the path, so htps://domain.com/event
and htps://domain.com/event/4
would both result in url: 'event'
(and should only be defined once).
Controller
This refers to the Component that should be loaded and should match one of the controllers in your Controllers
definition (shown above).
If this property is undefined the default page (the 'alias' controller in your Controllers
object) will be loaded.
In case the controller isn't defined in the Controllers
definition the 404 controller will be returned.
RedirectUrl
When a node with a redirectUrl is hit the tool will try to redirect to the corresponding url, if that isn't possible (for example when window
isn't defined) the Controllers.redirect
Component will be returned.
All together now
Your /pages/index.tsx will probably look something like this:
import KNR from "kingsquare-nextjs-routing"; import HomePage from "../myPages"; import AliasPage from "../myPages/[alias]"; import ErrorPage from "./_error"; import RedirectPage from "../myPages/redirect"; import FaqPage from "../myPages/faq"; const controllers = { home: HomePage, alias: AliasPage, 404: ErrorPage, redirect: RedirectPage, faq: FaqPage, }; const pageNodes = [ { url: '/', controller: 'home' }, // Returns the 'home' controller { url: '/foo' }, // Returns the 'alias' controller { url: '/bar', redirectUrl: '/foo' }, // Redirects to /foo { url: '/faq', redirectUrl: '/foo', controller: 'faq' }, // Redirects to /foo { url: '/frequently-asked-questions', controller: 'faq' }, // Returns the 'faq' controller ]; const Page = (pageProps) => { const { props, Component } = pageProps; return <Component {...props} />; }; Page.getInitialProps = async props => { return await KNR({ pageNodes, controllers, ...props }); };
Paths with multiple parts
Of course you can have paths with multiple parts, like /event/4
. As mentioned at the PageNodes section this will be handled by the same node as a path like /event
, but that doesn't mean /event
and /event/4
will result in the same outcome.
If the node has a defined controller the tool will change the controller that will be load. This is done by examining the last part of the path.
If the last part is a number the tool will change the controller to [original controller]Detail
, else the controller will become [original controller][last part of path]
.
For example, /event
will load controller Event
, /event/4
will load EventDetail
and /event/4/registration
will load EventRegistration
.
This will require the controllers object to contain the corresponding controllers:
import EventPage from "../myPages/event"; import EventDetailPage from "../myPages/event/[id]"; import EventRegisterPage from "../myPages/event/[id]/register"; const controllers = { event: EventPage, eventDetail: EventDetailPage, eventRegistration: EventRegisterPage, };