Next.js routing

Static and dynamic routing with Next.js

view on github

Next.js static routing

✔️ Static routing with next.js is pretty simple given that the app routes hierarchy will exactly mirror the contents of the /pages folder on the server, be it in development mode or at build time. For example, if a user agent requests /some/content :

  • If the /pages/some/content.jsx file exists, the request is served.
  • If it doesn't exist, the server responds with a HTTP 404 error.

Next.js dynamic routing

✔️ The next.js pre-rendering features cover 2 uses cases when it comes to dynamic content generation :

  • Pages contents depend on external data (use case for getStaticProps and getServerSideProps).
  • Pages paths depend on external data, for instance the site hierarchy depends on file system reads or database queries.
  • The latest is the typical use case for getStaticPaths, which enables dynamic routing in a next.js app.
  • getStaticPaths behaves exactly like getStaticProps : it runs at every request in development mode, then runs only once at build time.

Dynamic routing conventions

✔️ Dynamic routing is enabled in next.js through the use of dynamic segments - this concept can be thought of as :

  • Allow the use of wildcards in the supported server routes by enclosing route segments in brackets : /dynamic/[path].
  • Have the server dynamically generate a route when hit with a request that matches a route with dynamic segments.
  • Serve the request using bracket-enclosed pages in the /pages folder hierarchy : /pages/dynamic/[path].jsx.

✔️ Dynamic routes generation

  • If a page has to support dynamic routing (ie. it serves requests for routes w/ dynamic segments) it has to export getStaticPaths
  • For instance, in /pages/dynamic/[path].jsx :
const
    // async retrieval of ids to populate the
    // list of pages to statically generate
    getStaticPaths = () => ({
        // all routes defined here will be statically generated and
        // handled by the current page - the list must include a
        // specific route for each possible value of the dynamic segment
        // if the dynamic segment value is not in this list -> 404
        paths: [
            // matches /dynamic/pageone
            params: {path: `pageone`},
            // matches /dynamic/pagetwo
            params: {path: `pagetwo`},
            // matches /dynamic/pagethree
            params: {path: `pagethree`}
        ],
        // this is the value to set when using next for SSG - the other
        // possible values (`true` and `blocking`) are only relevant in
        // the context of an SSR capable app for which a small subset of
        // routes are to be statically generated at build time and other
        // routes are meant to be generated on demand
        fallback: false
        // essentially, this value tells how to run getStaticProps when
        // 1 - the app receives a request for a dynamic route.
        // 2 - the route for the dynamic segment value was not exported
        // by getStaticPaths thus not generated at build time.
    });

// export static paths generation function in a namespace
export {getStaticPaths};
  • The params object matching the requested dynamic route will be passed to the page's getStaticProps export :
    // async retrieval of props for static site generation
    getStaticProps = async context => {
        const
            // read dynamic route segments values from context
            {params: {path}} = context;

        // use the segments values to retrieve relevant data ... 

        // and pass it as props to the page for rendering
        return {props: {relevantData}};
    };

✔️ Catch-all segments

  • Catch-all segments are a specific types of dynamic segments that will match all subsequent segments of a dynamic route.
  • As a result, the dynamic segments values in the getStaticPaths export can be arrays :
const
    // ...
    getStaticPaths = () => ({
        // ...
        paths: [
            // matches /dynamic/page/one
            params: {path: [ `page`, `one` ]}
            // matches /dynamic/page/two
            params: {path: [ `page`, `two` ]}
            // ...
        ],
        // ...
    });

// export static paths generation function in a namespace
export {getStaticPaths};
  • To use catch-all segments for dynamic routing in a page, add an ellipsis inside the brackets : /pages/dynamic/[...path].jsx.