I've implemented a map between "pretty url" to a real page.
This implementation has few benefits.
- pretty urls can come from db
- pretty urls can be in any structure (not related to dir structure)
- pretty urls can be in any language :] (you have control over what your api returns as a url)
- the entire app is agnostic to them
- allows u to manipulate all the urls at one place (add prefix or what ever)
In a nutshell, I have a simple object that looks like:
const routes = {
pageName: (prettyUrl) => ({href: 'path/to/page', as: prettyUrl});
}
Both client & server are using this object.
Client
The api returns for each data that has page a url property from the db.
Let's consider that our app shows list of users & a user, that means that the API returns for each user it pretty url (it can be anything must be unique).
import { routes } from '../routes';
import NextLink from 'next/link';
export const userCard = ({ user }) => (
<div>
<NextLink {...routes.userPage(user.url)}>{user.name}</NextLink>
</div>
);
Server
I've a custom express server that loads from DB the mapping (url -> pageName).
const express = require('express');
const next = require('next');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handle = app.getRequestHandler();
app.prepare().then(async () => {
const urlsMap = await loadUrlsMap();
const server = express();
server.get('*', (req, res) => {
if (urlMaps.hasOwnProperty(req.pathname)) {
const page = urlMaps(req.pathname);
const additionalData = {}; // can have query / params from req
return app.render(req, res, page.href, { ...additionalData });
}
return handle(req, res);
});
server.listen(port, err => {
if (err) throw err;
console.log(`> Ready on http://localhost:${port}`);
});
});
I've showed a really basic implementation, but think that you can pass to the routes.pageName method any thing (userId, for example) and each method can do any logic with it and return { href, as }.
In my real implementation I'm using path-to-regex which allows me to pass a url template and more :]