fridays / next-routes

Universal dynamic routes for Next.js
MIT License
2.47k stars 230 forks source link

Support now 2.0 #252

Closed jesstelford closed 1 year ago

jesstelford commented 5 years ago

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.

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?

barnebys commented 5 years ago

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 commented 5 years ago

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

revskill10 commented 5 years ago

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