next-avenues
v0.8.4
Published
A fancy dynamic router for Next.js heavily inspired on Adonis.js and next-routes
Downloads
8
Maintainers
Readme
Next Avenues
A fancy dynamic router for Next.js heavily inspired on Adonis.js and next-routes
What's in the box?
- Adonis.js like syntax for building routes
- Request handler middleware for express & co
- Link and Router that generate URLs by route definition
- Ability to use domains and subdomain parameters
- Group routes and apply a prefix, domain or extra route data to all of your routes
How to use?
Install
npm install next-avenues --save
Create a routes.js file inside your project
// ./routes.js
const { router } = require('next-avenues');
router.add('/', 'index').as('homepage');
router.add('/blog-item/:slug', 'blog')
.as('blog-item')
.export(async() => {
return [
{ slug: 'my-first-article' },
{ slug: 'another-article' }
]
})
router
.group(() => {
router.add('/', 'admin-dashboard').as('admin-dashboard');
})
.prefix('admin');
module.exports = router;
The routes file will be used by the server and the client.
Server implementation
Create a custom server.js and implement the router.getRequestHandler middleware. For more information about creating a custom next.js server configuration goto Next.js documentation
Example implementation:
// ./server.js
const next = require('next');
const http = require('http');
const router = require('./routes');
const port = 3002;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handleNextRequests = router.getRequestHandler(app);
app.prepare().then(() => {
const server = new http.Server((req, res) => {
app.setAssetPrefix('');
return handleNextRequests(req, res);
});
server.listen(port, (err) => {
if (err) {
throw err;
}
console.log(`> Ready on http://localhost:${port}`);
});
});
Replace the scripts part in your package.json file with following configuration:
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "NODE_ENV=production node server.js"
}
Static export implementation
Create a next.config.js file and implement the withExportPathMap function. This will automaticly generate the next.js exportPathMap config based up on your routes.js file and the export function Example implementation
//./next-config.js
const routes = require('./routes');
module.exports = routes.withExportPathMap({});
Replace the scripts part in your package.json file with following configuration:
"scripts": {
"dev": "node server.js",
"build": "next build",
"export": "next export"
}
The page component (the basic implementation)
To get the route data you need to import the routes.js file and call the router.getCurrentRoute function.
// ./pages/BlogItem.js
import routes from '../routes';
export default class BlogItem extends React.Component {
static async getInitialProps() {
// Retrieve the current route data
const route = routes.getCurrentRoute();
return { route };
}
render() {
// this.props.route.params.slug
}
}
The page component (the advanced implementation)
Most of the times you'll want an _app.js component which does the call to your current route and passes it down to your page component.
// ./pages/_app.js
import React from 'react';
import App, { Container } from 'next/app';
import routes from '../routes';
export default class MyApp extends App {
static async getInitialProps({ Component, ctx }) {
let pageProps = {};
// Get current route info.
const route = routes.getCurrentRoute();
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx, route);
}
return { pageProps, route };
}
render() {
const { Component, pageProps, route } = this.props;
return (
<Container>
<Component {...pageProps} route={ route }/>
</Container>
);
}
}
Now you can access the route data in every page component like this:
// ./pages/BlogItem.js
import routes from '../routes';
export default class BlogItem extends React.Component {
static async getInitialProps(ctx, route) {
// route.params.slug
}
render() {
// this.props.route.params.slug
}
}
Link component
Use the Link component to generate links based on route name
For example consider following routes.js in the root of your project.
// ./routes.js
const router = require('next-avenues');
router.add('/', 'index').as('homepage');
router.add('/blog-item/:slug', 'blog').as('blog-item');
router
.group(() => {
router.add('/', 'admin-dashboard').as('dashboard');
})
.name('admin')
.domain(':subdomain.someurl.com')
.prefix('admin');
module.exports = router;
Then you can for example create following Link instances:
// ./components/LinkExample.js
import { Link } from 'next-avenues';
const LinkExample = () => (
<div>
<Link name='homepage'><a>Homepage</a></Link>
// this resolves to a link with following href: '/'
<Link name='blog-item' params={{ slug:'some-article' }}><a>A blog post</a></Link>
// this resolves to a link with following href: '/blog-item/some-article'
<Link name='admin.dashboard' params={{ subdomain:'some-subdomain' }}><a>A complex route url</a></Link>
// this resolves to a link with following href: 'http://some-subdomain.someurl.com/admin/'
</div>
)