Next.js: Serverless: Allow passing query and route params to render

Created on 17 Feb 2019  ·  13Comments  ·  Source: vercel/next.js

Feature request

Is your feature request related to a problem? Please describe.

With server target, if you want pretty urls like /blog/:slug?query1=ex the recommended approach is spin up a custom server and use something like app.render(req, res, page, queryStringAndRouteparams). Then in getInitialProps you can access both slug and query1 via ctx.query. This works great with server target because app.render supports passing querystring and route params.

With the Serverless target, getInitialProps won't' receive both querystring and route params in ctx.query because the exported render method can only access req and res object.

Describe the solution you'd like

I would like to propose api parity between app.render and the exported render in both serverless and server target. At the very least, allow passing queryparams as a third argument to the render method in serverless. Here: https://github.com/zeit/next.js/blob/da3c3aded134275abf158475a948a5f09a6f205b/packages/next/build/webpack/loaders/next-serverless-loader.ts#L76
export async function render (req, res, queryParams) {

Describe alternatives you've considered

Alternative today is to do conditional checks in getInitialProps like if (ctx.req) { // use ctx.req.params.slug }
next-routes sort of solves this problem today but doesn't work with serverless target.

happy to send a PR to update the render method in serverless to accept queryParam as the third argument

Most helpful comment

But this sounds like you're using the serverless target to create one big server holding all routes, which is contradictory to what the serverless target is for.

All 13 comments

i would like to not just pass queryParams, but also pass arbitrary info that i can fetch inside of my serverless function. is there a way to pass that into context? i cant figure it out.

@sw-yx why would you need to? It's generally an anti-pattern to do so, you can use getInitialProps for this.

Not allowing query was actually by design, as it means you are forced to implement routing on the proxy layer, otherwise people are going to inevitably create a custom server that imports all serverless functions which is slower than the server target 😅

why would you need to? It's generally an anti-pattern to do so, you can use getInitialProps for this.

I tried that, but unfortunately it seems like my isomorphic fetch inside getInitialProps is somehow being sandboxed and i didnt know how to debug why thats happening (and i dont think its nextjs' fault) whereas I -do- know that fetch inside my serverless function does work. so i was trying to pass it down 😅

its ok if youre not allowing it. just trying to fix my own situation.

otherwise people are going to inevitably create a custom server that imports all serverless functions which is slower

that's a fair point and I understand what we are trying to safeguard here. We can call that out very explicitly in our docs?

If we are going to debug in server and deploy in serverless, I think it's important to have basic parity between the two targets.

Having that warning in docs and making query an optional third argument to render should ensure those who don't need a custom server won't use it but ensure those who do need it have an option.

@timneutkens does that make sense? happy to send a PR with that docs update if you are onboard.

@timneutkens - It was simple enough so i opened a WIP PR to see if there is interest here: https://github.com/zeit/next.js/pull/6342

Timely issue. I ran into this recently. Thanks @chirag04. If nothing else, I learned something today.

Not allowing query was actually by design, as it means you are forced to implement routing on the proxy layer, otherwise people are going to inevitably create a custom server that imports all serverless functions which is slower than the server target 😅

that's a fair point and I understand what we are trying to safeguard here. We can call that out very explicitly in our docs?

If we are going to debug in server and deploy in serverless, I think it's important to have basic parity between the two targets.

Perhaps an example of how to implement routing on the proxy layer – specifically how the Next folks envisioned this working. I realize this more of a node thing than a Next thing but there seems to be some confusion around this. A if (ctx.req){...} isn't a big deal but it would be quite nice if params were colocated in query on the client and server.

It's hard to give an example as it depends on your hosting platform. In case on Now you can read this to see how it works: https://zeit.co/guides/custom-next-js-server-to-routes/

You can do similar things in nginx etc.

@timneutkens - Thanks for sharing that article. Glad that something like this is already supported out-of-box in now.

You can do similar things in nginx etc.

I would rather not spin an Nginx server just to have access to route params in getInitialProps via my express route handler(we are not using now). Also, nginx is one more thing to run locally for debugging. 🤷‍♂️

Sounds like those not using now will ultimately arrive at this problem and allowing query argument to render method will simplify a lot of things in those cases.

But this sounds like you're using the serverless target to create one big server holding all routes, which is contradictory to what the serverless target is for.

@chirag04 - would you mind sharing a few snippets of code or repo that demonstrates your issue?

Our problem was that we wanted a unified way of having access to route params in our getInitialProps method. This article https://zeit.co/guides/custom-next-js-server-to-routes/ answered pretty much everything.

Going to close. thanks every for helping.

can some one help me with changing this:

server.get('/rooms/south-africa/pretoria', (req, res) => {
    return app.render(req, res, '/rooms', {
      lat: -25.7478676,
      lng: 28.22927119999997,
      location: 'Pretoria',
    })
  });

in to this now example you guys talking about:

{
  "version": 2,
  "routes": [
    { "src": "/product/(?<name>[^/]+)$", "dest": "/product?name=$name" }
  ]
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

formula349 picture formula349  ·  3Comments

YarivGilad picture YarivGilad  ·  3Comments

timneutkens picture timneutkens  ·  3Comments

flybayer picture flybayer  ·  3Comments

knipferrc picture knipferrc  ·  3Comments