next-routes icon indicating copy to clipboard operation
next-routes copied to clipboard

Support now 2.0

Open jesstelford opened this issue 6 years ago • 3 comments

Now 2.0 has been released: https://zeit.co/blog/now-2

Specifically, the next.js docs encourage not using a file that specifies all the routes:

It might be tempting to use the now/node-server Builder, as seen in the example above, to quickly deploy your app as a Lambda without any code changes.

Keep in mind, however, that one of the benefits of the serverless model, as the name implies, is not only not to manage servers, but also not to think in terms of the server abstraction.

In other words, if you are writing new Server() (in whatever language you prefer), you might be missing out on the granularity benefits of serverless.

For example, many people have throughout the years provided examples on how to deploy express, a Node.js framework, to AWS Lambda:

app.get('/', myFunction)
app.get('/2nd-route', myOtherFunction)
app.get('/third-route', myThirdFunction)

With Now, you can split this into three discrete underlying Lambdas instead, which allows for:

  • Reduced surface of error
  • Faster cold boot times thanks to smaller bundle sizes ("code splitting" for the backend)
  • Per-route scalability
  • Faster build and, therefore, total deployment times

As seen above, the code changes required to leave servers behind altogether are very minimal, while the benefits very significant.

  • https://zeit.co/docs/v2/platform/upgrade-to-2-0#don-t-rush-to-upgrade/serverless-is-better-without-servers

The alternative proposed is to use a now.json#routes config: https://zeit.co/docs/v2/deployments/configuration#routes

{
  "builds": [
    { "src": "*.html", "use": "@now/static" },
    { "src": "*.js", "use": "@now/node" },
  ],
  "routes": [
    { "src": "/custom-page", "headers": {"cache-control": "s-maxage=1000"}, "dest": "index.html" },
    { "src": "/api", "dest": "my-api.js" },
    { "src": "/users/(?<id>[^/]", "dest": "users-api.js?id=$id" },
    { "src": "/.*", "dest": "https://my-old-site.com"},
    { "src": "/legacy", "status": 404},
    { "src": "/redirect", "status": 301, "headers": { "Location": "https://zeit.co/" } }
  ]
}

However, this loses the ability to do reverse-route lookups which I love from next-routes.

Is there a way to interop the two concepts and reap benefits of both?

jesstelford avatar Nov 08 '18 21:11 jesstelford

We just manage to build it for Now 2.0 as a POC. Sharing the solution here and if no one beats us to it we will try to do a PR with a better solution asap.

const fs = require("fs");

const nextRoutes = require("../routes");
const nowConfig = require("../now.json");

if(!nowConfig.routes) {
    nowConfig.routes = []
}

nextRoutes.routes.forEach((route) => {
    if (nowConfig.routes.filter(e => e.src === route.regex.source).length === 0) {
        nowConfig.routes.push({
            src: route.regex.source,
            dest: route.page
        })
    }
})

fs.writeFile('now.json', JSON.stringify(nowConfig, false, 2), (err) => {
    if (err) {
        console.error(err);
        return;
    };
    console.log("now.json has been updated");
});

The idea is simply to fetch routing and update now.json with it. That would keep it backwards compatible with link generation using named routes in this package.

barnebys avatar Nov 27 '18 16:11 barnebys

We wrote a simple CLI tool for this based on the above POC. https://www.npmjs.com/package/next-routes-now

barnebys avatar Nov 28 '18 09:11 barnebys

I created my own routes middleware to use Now 2.0 json routing format here

revskill10 avatar Dec 01 '18 06:12 revskill10