This package has been deprecated

Author message:

This package has been deprecated and recommend to use next-typed-routes instead.

now-next-routes
TypeScript icon, indicating that this package has built-in type declarations

1.1.3 • Public • Published

📦 DEPRECATED 📦

This package has been deprecated and recommend to use "next-typed-routes" instead.


now-next-routes

🔜 Dynamic routes for Next.js on Now 🔙

// /routes.ts
export default {
  "users/user": new Route<{ userId: number }>({ page: "/users/user", pattern: "/users/:userId" }),
  "users/profile": new Route<{ userId: number }>({ page: "/users/profile", pattern: "/users/:userId/profile" }),
};

// /pages/users.tsx
import routes from "./routes.ts";

const userPageLinkProps = routes["users/user"].getLinkProps({ userId: 1 });
export default () => (
  <Link {...userPageLinkProps}>
    <a>Go to the first user page</a>
  </Link>
);

// $ npx now-next-routes generate routes.ts
// then ... now.json is generated!!
//
// /now.json
{
  ...
  "routes": [
    {
      "src": "^\\/users\\/([^\\/]+?)\\/?$",
      "dest": "users/user?userId=$1"
    },
    {
      "src": "^\\/users\\/([^\\/]+?)\\/profile\\/?$",
      "dest": "users/profile?userId=$1"
    }
  ]
}
npm CircleCI license @jagaapple_tech

Table of Contents

Features

FEATURES WHAT YOU CAN DO
❤️ Designed for Next.js and ZEIT Now Don't need to manage routes property in now.json
🌐 Build for Serverless Custom servers are not required
📄 Write once, Manage one file All you need is write routes to one file
🎩 Type Safe You can get errors when missing required dynamic URL parameters

Motivation

Next.js has file-system routing, but it does not provide dynamic routing. In the strict sense, it is possible to implement dynamic routing if you adopt custom servers such as Express.js. Famous libraries which provide dynamic routes such as next-routes and nextjs-dynamic-routes require to use custom servers too.

On the other hand, ZEIT that develops and manages Next.js provides FaaS called Now. I definitely think it is the best way to hosting Next.js apps. Now adopts serverless architecture, so you can deploy Next.js app very easily, all you need is to write now.json with @now/next . ZEIT recommends to deploy one page on one lambda in order to get benefits of serverless and @now/next conforms it automatically. However you need use @now/node or @now/node-server if you adopt custom servers. In other words, to use custom servers in Next.js on Now is bad.

The best way is to use no custom servers and set routes property in now.json to your application routes, but it has very low maintainability because you need to write the same route settings twice and complex regular expressions.

now-next-routes was created in order to resolve these issues. now-next-routes provides a command to create routes property in now.json from a specific route definitions and also provides functions to create links high type safety.

Quick Start

Requirements

  • Node.js 8.0.0 or higher
  • npm or Yarn

Installation

$ npm install --save-dev now-next-routes

If you use Yarn, use the following command.

$ yarn add --dev now-next-routes

Usage

Defines routes

// /routes.ts
import { Route } from "now-next-routes";

export default {
  // Index
  index: new Route({ page: "/index", pattern: "/" }),

  // Users
  "users/users": new Route({ page: "/users/users", pattern: "/users" }),
  "users/user": new Route<{ userId: number }>({ page: "/users/user", pattern: "/users/:userId" }),

  // Users - Comments
  "comments/comment": new Route<{ userId: number; commentId: number }>({
    page: "/comments/comment",
    pattern: "/users/:userId/comments/:commentId",
  }),
};

First, you need to define routes using now-next-routes. A point that must be keep in your mind is to export as default value using export default syntax.

Arguments of Route constructor

now-next-routes exports Route class which provides to create objects for Next.js and Now. A route should be an object which has a page identifier as key and Route object as value.

Currently, a constructor of Route accepts an object which has two properties.

  • page: string ... A page of Next.js. This is a path of files in /pages in general.
  • pattern: string ... An actual URL pattern. Dynamic parameters should follow the format :parameterName .

Gets more type safety

new Route<{ userId: number }>({ page: "/users/user", pattern: "/users/:userId" });

Also the constructor accepts one generic type. This type is to improve type safety when you create links with dynamic parameters. If a route requires dynamic parameters and your project is written by TypeScript, I recommended to specify. The type should be an object literal type and properties should be matched dynamic parameters you write in pattern .

Generates routes for Now

now-next-routes also provides a command to generate routes for Now.

$ npx now-next-routes generate routes.ts

generate command generates routes property of now.json from a routes file you created like the following.

{
  "routes": [
    {
      "src": "^\\/?$",
      "dest": "index"
    },
    {
      "src": "^\\/users\\/?$",
      "dest": "users/users"
    },
    {
      "src": "^\\/users\\/([^\\/]+?)\\/?$",
      "dest": "users/user?userId=$1"
    },
    {
      "src": "^\\/users\\/([^\\/]+?)\\/comments\\/([^\\/]+?)\\/?$",
      "dest": "comments/comment?userId=$1&commentId=$2"
    }
  ]
}

If now.json exists, this command overwrite routes property in it. Otherwise, this command creates now.json file.

Creates links

import routes from "./routes.ts";

const userPageLinkProps = routes["users/user"].getLinkProps({ userId: 1 });
const Component = () => (
  <Link {...userPageLinkProps}>
    <a>Go to the first user page</a>
  </Link>
);

An object of Route class provides getLinkProps function. This is to create props of built-in <Link> component provided by Next.js.

Specifically this function returns an object which has href and as properties. So you can also write like the following.

<Link href={userPageLinkProps.href} as={userPageLinkProps.as}>

Uses in Router.push()

Router.push() function provided from next/router makes you to be possible to move to some pages programmatically. This function also accepts href and as values as arguments, so you can give parameters using getLinkProps() .

Router.push(userPageLinkProps.href, userPageLinkProps.as);

Type safety

now-next-routes is designed by TypeScript. So you can create links type safety from routes you crated if you gives generic types when calling constructors.

const userPageLinkProps = routes["users/user"].getLinkProps({ userId: "1" });
                                                              ^^^^^^
                // Type 'string' is not assignable to type 'number'. ts(2322)

Recipes

Gets type safety in a page when handling queries

import { DynamicParameters } from "now-next-routes";

type Query = DynamicParameters<typeof routes["users/user"]>;
Component.getInitialProps = (ctx) => {
  const query = ctx as Query;
  const userId = query.user_id;
                       ^^^^^^^
  // Property 'user_id' does not exist on type 'Partial<{ userId: number; }>'.
  // Did you mean 'userId'? ts(2551)

  ...

  return { userId: query.userId };
};

DynamicParameters type exported by now-next-routes accepts a type of Route object. It returns a type of dynamic parameters. It is helpful for handling queries type safety in getInitialProps .

Preserves original now.json

By default, now-next-routes overwrites or creates now.json file. It is possible to output as other file when you specify --input or --output option.

# Inputs from a template file and outputs as `now.json` .
$ npx now-next-routes generate --input now.sample.json routes.ts

# Inputs from `now.json` and outputs as a specific file name.
$ npx now-next-routes generate --output now-production.json routes.ts

If your now.json already has custom routes property, it is possible to merge generated routes to it and you should use --merge option.

API

CLI

$ npx now-next-routes --help
Usage: now-next-routes [options] [command]

Options:
  -v, --version                     output the version number
  -h, --help                        output usage information

Commands:
  generate [options] <routes-file>  generate routes for now.json
  *

generate

$ npx now-next-routes generate --help                                                                                                                                                                              (06/03 06:45:54)
Usage: generate [options] <routes-file>

generate routes for now.json

Options:
  -i, --input <path>   now.json file path
  -o, --output <path>  an output now.json file path
  -m, --merge          merge into existing "routes" property
  -h, --help           output usage information

Route Class

constructor<Parameters>(settings: Settings): Route

new Route<{ userId: number }>({ page: "/users/user", pattern: "/users/:userId" });

Returns a new object of Route class.

  • Parameters ... A generic type to specify types of dynamic parameters (for TypeScript).
  • settings: Settings
    • page: string ... A page file path in /pages directory of Next.js.
    • pattern: string ... A mapping path pattern. The format :parameterName will be mapped to dynamic parameters.

Route.prototype.getLinkProps(parameters: Parameters): LinkProps<Parameters>

route.getLinkProps({ userId: number });

Returns LinkProps<Parameters> object.

  • Parameters ... Types of dynamic parameters you gave to constructor (for TypeScript).
  • LinkProps<Parameters>
    • href: object
      • pathname: string ... A base path name. This is a page file path in /pages in general.
      • query: Partial<Parameters> ... Displayed URL string in web browsers.
    • as: string ... A mapped URL.

Route.prototype.getPaths(parameters: Parameters): Paths

route.getPaths({ userId: number });

Returns Paths object.

  • Parameters ... Types of dynamic parameters you gave to constructor (for TypeScript).
  • Paths
    • href: string ... A full path which contains a page file path in /pages and query string.
    • as: string ... A mapped URL.

Route.prototype.createRouteForNow(): object

route.createRouteForNow();

Creates an object for routes property in now.json for ZEIT Now. This method is used in CLI, so you don't need to use this method in general. This method will be changed without any notices.

DynamicParameters<T extends Route>

type Parameters = { userId: number };

const route = new Route<Parameters>({ page: "users/user", pattern: "/users/:userId" })
type Query = DynamicParameters<typeof route>; // Partial<{ userId: number }>

Returns a type you gave to a constructor of Route . A returned type is weak type.

Contributing to now-next-routes

Bug reports and pull requests are welcome on GitHub at https://github.com/jagaapple/now-next-routes. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the Contributor Covenant code of conduct.

Please read Contributing Guidelines before development and contributing.

License

The library is available as open source under the terms of the MIT License.

Copyright 2019 Jaga Apple. All rights reserved.

Package Sidebar

Install

npm i now-next-routes

Weekly Downloads

1

Version

1.1.3

License

MIT

Unpacked Size

28.8 kB

Total Files

12

Last publish

Collaborators

  • jagaapple