quarkus-quinoa icon indicating copy to clipboard operation
quarkus-quinoa copied to clipboard

NextJS: PageRouter issue using direct URL

Open UbiquitousBear opened this issue 1 year ago • 33 comments

Describe the bug

When I navigate directly to any non-root URL e.g. http://localhost:8080/components/[id] or http://localhost:8080/components/, the contents of http://localhost:8080/ (ie src/pages/index.tsx is shown. If it try the same request over the nextjs dev server directly, ie http://localhost:3000/components/[id] the routing works as expected.

Inspecting the state of next/router shows that the path is picked up, but nothing else is. Unsure whether this is a next issue or a quinoa issue.

Quinoa version

2.4.3

Quarkus version

3.12.3

Build / Runtime

Next.js

Package Manager

PNPM

Steps to reproduce the behavior

next14-quinoa.zip

Unzip and run mvn quarkus:dev and navigate to http://localhost:8080 it uses Next App Router and the dynamic slugs work fine.

However naivgate directly to http://localhost:8080/post/2020/first-post/with/catch/all/routes and it loses the route.

Expected behavior

No response

UbiquitousBear avatar Jul 22 '24 18:07 UbiquitousBear

@UbiquitousBear have you read the section on SPA: https://docs.quarkiverse.io/quarkus-quinoa/dev/advanced-guides.html#spa-routing

See both the NOTE and the WARNING.

melloware avatar Jul 22 '24 19:07 melloware

@melloware

Note: By default, Quinoa will ignore quarkus.resteasy-reactive.path, quarkus.resteasy.path and quarkus.http.non-application-root-path path prefixes. You can specify different path prefixes to ignore using quarkus.quinoa.ignored-path-prefixes.

Warning: Currently, for technical reasons, the Quinoa SPA routing configuration won’t work with RESTEasy Classic. Instead, you may use a workaround (if your app has all the rest resources under the same path prefix):

To clarify, I'm using the graphql extension, which exposes /graphql, so I don't think the cases fall under either, unless /graphql should be defined under quarkus.quinoa.ignored-path-prefixes ?

UbiquitousBear avatar Jul 22 '24 22:07 UbiquitousBear

Yeah I am wondering the same thing.

Any way you can try it out or put together a small runnable reproducer?

melloware avatar Jul 22 '24 22:07 melloware

Also did you enable spa routing? A runnable reproducer will help figure it out.

melloware avatar Jul 22 '24 22:07 melloware

@melloware I've enabled SPA routing, whilst I can't isolate the example (simply due to lack of time this week), I am more than happy to push the whole thing to a private GH repo if that helps?

UbiquitousBear avatar Jul 23 '24 00:07 UbiquitousBear

Sure it might help me if I can look at it and suggest some changes.

melloware avatar Jul 23 '24 00:07 melloware

@melloware invited :)

UbiquitousBear avatar Jul 23 '24 00:07 UbiquitousBear

Thanks I will check it out tomorrow

melloware avatar Jul 23 '24 01:07 melloware

@UbiquitousBear try this. next14-quinoa.zip

Unzip and run mvn quarkus:dev and navigate to http://localhost:8080 it uses Next App Router and the dynamic slugs work fine.

This proves Quinoa and SPA is working.

you might want to check if its all that Atlassian Code or other things you have going on in your complex project.

melloware avatar Jul 23 '24 13:07 melloware

@melloware if you navigate directly to http://localhost:8080/post/2020/first-post/with/catch/all/routes in your browser, does it still work?

When I go to that URL directly, I see:

[Home](http://localhost:8080/)
[About](http://localhost:8080/about)
[First Post](http://localhost:8080/post/2020/first-post/with/catch/all/routes)
[Second Post](http://localhost:8080/post/2020/second-post/with/catch/all/routes)
Hello World!

UbiquitousBear avatar Jul 23 '24 13:07 UbiquitousBear

Ahhh it works when i click the Next links but not directly do the URL in the browser. Let me look.

melloware avatar Jul 23 '24 14:07 melloware

Interesting so when you click the link here is what Next Generates:

http://localhost:8080/_next/static/chunks/pages/post/%5B...slug%5D.js

Which is not the same as

http://localhost:8080/post/2020/first-post/with/catch/all/routes

melloware avatar Jul 23 '24 14:07 melloware

Assigned to @ia3andy i am not quite sure how this route is being lost.

melloware avatar Jul 23 '24 14:07 melloware

@all-contributors add @UbiquitousBear for bug

melloware avatar Jul 23 '24 14:07 melloware

@melloware

I've put up a pull request to add @UbiquitousBear! :tada:

allcontributors[bot] avatar Jul 23 '24 14:07 allcontributors[bot]

@melloware trying with 2.4.4, still not fixed?

UbiquitousBear avatar Jul 26 '24 10:07 UbiquitousBear

No. No fix was made I only tweaked how it discovers NextJS but not your issue which is why it's still open.

melloware avatar Jul 26 '24 10:07 melloware

Ah ok - I wonder if it's something to do with how rewriting is forwarded. I believe the same happens when I build the project into a jar for deployment.

UbiquitousBear avatar Jul 26 '24 10:07 UbiquitousBear

Yep it's something going on with SPA routing.

melloware avatar Jul 26 '24 11:07 melloware

I am debugging this. I think I am closer to seeing what is wrong.

melloware avatar Jul 26 '24 14:07 melloware

Here is what I have debugged:

[io.qua.qui.QuinoaSPARoutingHandler] (vert.x-eventloop-thread-2) Quinoa checking SPA request '/post/2020/second-post/with/catch/all/routes'
[io.qua.qui.QuinoaSPARoutingHandler] (vert.x-eventloop-thread-2) Mount Point: '/'  Route Path: '/'
[io.qua.qui.QuinoaSPARoutingHandler] (vert.x-eventloop-thread-2) Quinoa is re-routing SPA request '/post/2020/second-post/with/catch/all/routes' to '/'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/_next/static/chunks/webpack.js'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-3) Quinoa is forwarding: '/_next/static/development/_buildManifest.js'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/_next/static/chunks/pages/_app.js'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-3) Quinoa is forwarding: '/_next/static/chunks/pages/index.js'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/_next/static/development/_ssgManifest.js'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/_next/static/chunks/react-refresh.js'
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/_next/static/chunks/main.js'
[io.net.han.cod.htt.web.WebSocketServerHandshaker] (vert.x-eventloop-thread-2) [id: 0xf37380dd, L:/127.0.0.1:8080 - R:/127.0.0.1:49346] WebSocket version V13 server handshake
[io.net.han.cod.htt.web.WebSocketServerHandshaker] (vert.x-eventloop-thread-2) WebSocket version 13 server handshake key: nsM7SH5Cyulob732tXFtWA==, response: DQ/ZZpL7GZ78wggZGGsDlPWTqoc=
[io.qua.qui.QuinoaDevWebSocketProxyHandler] (vert.x-eventloop-thread-2) Quinoa Dev WebSocket Server Connected: 127.0.0.1:3000/_next/webpack-hmr
[io.net.han.cod.htt.web.WebSocketClientHandshaker13] (vert.x-eventloop-thread-2) WebSocket version 13 client handshake key: aoCqCGY1pUICRlB533ZAkA==, expected response: r5nmJp82/Efxbzl29S9GEE1HaX4=
[io.ver.cor.htt.imp.Http1xClientConnection] (vert.x-eventloop-thread-2) WebSocket handshake complete
[io.qua.qui.QuinoaDevWebSocketProxyHandler] (vert.x-eventloop-thread-2) Quinoa Dev WebSocket Client Connected: 127.0.0.1:3000/_next/webpack-hmr
[io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa is forwarding: '/_next/static/development/_devMiddlewareManifest.json'
[io.qua.qui.QuinoaDevWebSocketProxyHandler] (vert.x-eventloop-thread-2) Quinoa Dev WebSocket Client message: {"action":"sync","hash":"172eea221fcc05a4","errors":[],"warnings":[],"versionInfo":{"staleness":"fresh","installed":"14.2.5"}}
[io.qua.qui.QuinoaDevWebSocketProxyHandler] (vert.x-eventloop-thread-2) Quinoa Dev WebSocket Server message:  {"event":"client-success","clientId":1722003263354}
[io.qua.qui.QuinoaDevWebSocketProxyHandler] (vert.x-eventloop-thread-2) Quinoa Dev WebSocket Server message:  {"event":"span-end","startTime":1722003263180,"endTime":1722003263398,"spanName":"navigation-to-hydration","attributes":{"pathname":"/post/2020/second-post/with/catch/all/routes","query":""}}
[io.qua.qui.QuinoaDevWebSocketProxyHandler] (vert.x-eventloop-thread-2) Quinoa Dev WebSocket Server message:  {"event":"ping","page":"/"}

This websocket message back from Next is interesting.

Quinoa Dev WebSocket Server message:  {"event":"span-end","startTime":1722003263180,"endTime":1722003263398,"spanName":"navigation-to-hydration","attributes":{"pathname":"/post/2020/second-post/with/catch/all/routes","query":""}}

melloware avatar Jul 26 '24 14:07 melloware

Line 3, why is quinoa rerouting to /?

UbiquitousBear avatar Jul 27 '24 11:07 UbiquitousBear

@UbiquitousBear its explained right here: https://docs.quarkiverse.io/quarkus-quinoa/dev/advanced-guides.html#spa-routing

It looks like its successfully being sent to Next. But the response from Next is not the page it looks like somehow it stays routed to / but the WebSocket response from Next seems to indicate it knows the route happened.

melloware avatar Jul 27 '24 12:07 melloware

Could this be a nextjs bug? But wonder why it can't be reproduced using the dev server....

UbiquitousBear avatar Aug 02 '24 10:08 UbiquitousBear

I don't think so i think its just a matter of figuring out why Quinoa SPA handler is not handling NextJS 14 AppRouter. I used to have it working it older NextJS versions I think 12. But AppRouter is newer and NextJS seems to be changing every day.

melloware avatar Aug 02 '24 11:08 melloware

To clarify, the example (and where I'm see the issue) uses the Pages Router, not the App Router...

UbiquitousBear avatar Aug 02 '24 12:08 UbiquitousBear

I see a mention of hydration, are you sure there is no server side rendering in there?

ia3andy avatar Sep 05 '24 08:09 ia3andy

I see a mention of hydratation, are you sure there is no server side rendering in there?

what are you defining as hydration? Hydration is happening at some level, always does in React applications.

UbiquitousBear avatar Sep 05 '24 15:09 UbiquitousBear

@UbiquitousBear AFAIK hydration is happening only when the server is doing part of the work which is not the case for plain SPA no?

ia3andy avatar Sep 05 '24 15:09 ia3andy

@UbiquitousBear AFAIK hydration is happening only when the server is doing part of the work which is not the case for plain SPA no?

That's one definition of hydration when applied to the App Router. Hydration as-is, in client side generated apps still refers to attaching event listeners to the static HTML, making it dynamic at some level.

https://github.com/vercel/next.js/blob/cf62dccd850ce48429955463205dd0105e83ddbd/packages/next/src/client/index.tsx#L569 is calling the markHydrateComplete function which generates the span.

UbiquitousBear avatar Sep 05 '24 15:09 UbiquitousBear