Skip to content

Instantly share code, notes, and snippets.

@tricoder42
Created April 25, 2019 08:15
Show Gist options
  • Save tricoder42/bfedb4dc9a0ab980bf948c1880c4d269 to your computer and use it in GitHub Desktop.
Save tricoder42/bfedb4dc9a0ab980bf948c1880c4d269 to your computer and use it in GitHub Desktop.
Next.js Route Configs
// I believe this file could be automatically generated. Each route
// could be typechecked that all params are passed into it.
import { projectRoute } from "routes.js"
import { ProjectLink } from "routes.utils.ts"
export const ProjectLink = makeLink(projectRoute)
// Example usage of `ProjectLink` component. It's like regular Link, but it accepts `params`
// which are injected into `routeConfig.as` pattern.
const Example = () => (
<ProjectLink params={{user: "tricoder42", repository: "accent"}} passHref>
<TopMenuLink><Trans>Why accent?</Trans></TopMenuLink>
</ProjectLink>
)
// Just to compare both approaches, this is how it looks under the hood.
// Using `routes.js`, all routes are defined in single place. Each route is exported
// individually, so code-splitting and dead-code elimination should only include used
// routes on client.
const ExampleWithOriginalLink = () => (
<Link href="/project?user=tricoder42&repository=accent" as="/tricoder42/accent" passHref>
<TopMenuLink><Trans>Why accent?</Trans></TopMenuLink>
</ProjectLink>
)
// routeConfig defines how URL (`as` prop) is mapped to filesystem (`path` prop)
export const = projectRoute = {
path: `/project`,
as: '/:user/:repository',
}
import * as React from "react"
import Link, {LinkProps} from "next/link"
interface RouteLinkProps extends LinkProps {
params: {[key: string]: string},
}
interface RouteConfig {
path: string,
as: string,
}
// Create customized Link component, which fills `href` and `as` props based on routeConfig
export const makeLink = (routeConfig: RouteConfig) => ({ params, children, ...props }: RouteLinkProps) => {
const query = Object.entries(params).map(pair => pair.join("=")).join("&")
const href = `${routeConfig.path}?${query}`
const as = Object.entries(params).reduce((path, [key, value]) => path.replace(`:${key}`, value), routeConfig.as)
return <Link href={href} as={as} {...props}>{children}</Link>
}
const express = require('express')
const next = require('next')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
// Load route configs
const routes = require('./routes')
app
.prepare()
.then(() => {
const server = express()
/**
* For each route in config, define handler.
*/
Object.values(routes).forEach(routeConfig => {
server.get(routeConfig.as, (req, res) => {
app.render(req, res, routeConfig.path, req.params)
})
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(3000, err => {
if (err) throw err
console.log('> Ready on http://localhost:3000')
})
})
.catch(ex => {
console.error(ex.stack)
process.exit(1)
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment