1 | # Dynamic Routes for Next.js
|
2 |
|
3 | [![npm version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=js&type=6&v=1.4.2&x2=0)](https://www.npmjs.com/package/next-routes) [![Coverage Status](https://coveralls.io/repos/github/fridays/next-routes/badge.svg)](https://coveralls.io/github/fridays/next-routes) [![Build Status](https://travis-ci.org/fridays/next-routes.svg?branch=master)](https://travis-ci.org/fridays/next-routes)
|
4 |
|
5 | Easy to use universal dynamic routes for [Next.js](https://github.com/zeit/next.js)
|
6 |
|
7 | - Express-style route and parameters matching
|
8 | - Request handler middleware for express & co
|
9 | - `Link` and `Router` that generate URLs by route definition
|
10 |
|
11 | ## How to use
|
12 |
|
13 | Install:
|
14 |
|
15 | ```bash
|
16 | npm install next-routes --save
|
17 | ```
|
18 |
|
19 | Create `routes.js` inside your project:
|
20 |
|
21 | ```javascript
|
22 | const routes = module.exports = require('next-routes')()
|
23 |
|
24 | routes
|
25 | .add('about')
|
26 | .add('blog', '/blog/:slug')
|
27 | .add('user', '/user/:id', 'profile')
|
28 | .add('/:noname/:lang(en|es)/:wow+', 'complex')
|
29 | .add({name: 'beta', pattern: '/v3', page: 'v3'})
|
30 | ```
|
31 |
|
32 | This file is used both on the server and the client.
|
33 |
|
34 | API:
|
35 |
|
36 | - `routes.add(name, pattern = /name, page = name)`
|
37 | - `routes.add(pattern, page)`
|
38 | - `routes.add(object)`
|
39 |
|
40 | Arguments:
|
41 |
|
42 | - `name` - Route name
|
43 | - `pattern` - Route pattern (like express, see [path-to-regexp](https://github.com/pillarjs/path-to-regexp))
|
44 | - `page` - Page inside `./pages` to be rendered
|
45 |
|
46 | The page component receives the matched URL parameters merged into `query`
|
47 |
|
48 | ```javascript
|
49 | export default class Blog extends React.Component {
|
50 | static async getInitialProps ({query}) {
|
51 | // query.slug
|
52 | }
|
53 | render () {
|
54 | // this.props.url.query.slug
|
55 | }
|
56 | }
|
57 | ```
|
58 |
|
59 | ## On the server
|
60 |
|
61 | ```javascript
|
62 | // server.js
|
63 | const next = require('next')
|
64 | const routes = require('./routes')
|
65 | const app = next({dev: process.env.NODE_ENV !== 'production'})
|
66 | const handler = routes.getRequestHandler(app)
|
67 |
|
68 | // With express
|
69 | const express = require('express')
|
70 | app.prepare().then(() => {
|
71 | express().use(handler).listen(3000)
|
72 | })
|
73 |
|
74 | // Without express
|
75 | const {createServer} = require('http')
|
76 | app.prepare().then(() => {
|
77 | createServer(handler).listen(3000)
|
78 | })
|
79 | ```
|
80 |
|
81 | Optionally you can pass a custom handler, for example:
|
82 |
|
83 | ```javascript
|
84 | const handler = routes.getRequestHandler(app, ({req, res, route, query}) => {
|
85 | app.render(req, res, route.page, query)
|
86 | })
|
87 | ```
|
88 |
|
89 | Make sure to use `server.js` in your `package.json` scripts:
|
90 |
|
91 | ```json
|
92 | "scripts": {
|
93 | "dev": "node server.js",
|
94 | "build": "next build",
|
95 | "start": "NODE_ENV=production node server.js"
|
96 | }
|
97 | ```
|
98 |
|
99 | ## On the client
|
100 |
|
101 | Import `Link` and `Router` from your `routes.js` file to generate URLs based on route definition:
|
102 |
|
103 | ### `Link` example
|
104 |
|
105 | ```jsx
|
106 | // pages/index.js
|
107 | import {Link} from '../routes'
|
108 |
|
109 | export default () => (
|
110 | <div>
|
111 | <div>Welcome to Next.js!</div>
|
112 | <Link route='blog' params={{slug: 'hello-world'}}>
|
113 | <a>Hello world</a>
|
114 | </Link>
|
115 | or
|
116 | <Link route='/blog/hello-world'>
|
117 | <a>Hello world</a>
|
118 | </Link>
|
119 | </div>
|
120 | )
|
121 | ```
|
122 |
|
123 | API:
|
124 |
|
125 | - `<Link route='name'>...</Link>`
|
126 | - `<Link route='name' params={params}> ... </Link>`
|
127 | - `<Link route='/path/to/match'> ... </Link>`
|
128 |
|
129 | Props:
|
130 |
|
131 | - `route` - Route name or URL to match (alias: `to`)
|
132 | - `params` - Optional parameters for named routes
|
133 |
|
134 | It generates the URLs for `href` and `as` and renders `next/link`. Other props like `prefetch` will work as well.
|
135 |
|
136 | ### `Router` example
|
137 |
|
138 | ```jsx
|
139 | // pages/blog.js
|
140 | import React from 'react'
|
141 | import {Router} from '../routes'
|
142 |
|
143 | export default class Blog extends React.Component {
|
144 | handleClick () {
|
145 | // With route name and params
|
146 | Router.pushRoute('blog', {slug: 'hello-world'})
|
147 | // With route URL
|
148 | Router.pushRoute('/blog/hello-world')
|
149 | }
|
150 | render () {
|
151 | return (
|
152 | <div>
|
153 | <div>{this.props.url.query.slug}</div>
|
154 | <button onClick={this.handleClick}>Home</button>
|
155 | </div>
|
156 | )
|
157 | }
|
158 | }
|
159 | ```
|
160 |
|
161 | API:
|
162 |
|
163 | - `Router.pushRoute(route)`
|
164 | - `Router.pushRoute(route, params)`
|
165 | - `Router.pushRoute(route, params, options)`
|
166 |
|
167 | Arguments:
|
168 |
|
169 | - `route` - Route name or URL to match
|
170 | - `params` - Optional parameters for named routes
|
171 | - `options` - Passed to Next.js
|
172 |
|
173 | The same works with `.replaceRoute()` and `.prefetchRoute()`
|
174 |
|
175 | It generates the URLs and calls `next/router`
|
176 |
|
177 | ---
|
178 |
|
179 | Optionally you can provide custom `Link` and `Router` objects, for example:
|
180 |
|
181 | ```javascript
|
182 | const routes = module.exports = require('next-routes')({
|
183 | Link: require('./my/link')
|
184 | Router: require('./my/router')
|
185 | })
|
186 | ```
|
187 |
|
188 | ---
|
189 |
|
190 | ##### Related links
|
191 |
|
192 | - [zeit/next.js](https://github.com/zeit/next.js) - Framework for server-rendered React applications
|
193 | - [path-to-regexp](https://github.com/pillarjs/path-to-regexp) - Express-style path to regexp
|