reflex-dev / reflex

πŸ•ΈοΈ Web apps in pure Python 🐍
https://reflex.dev
Apache License 2.0
18k stars 997 forks source link

Investigate NextJS API routes #121

Closed picklelo closed 1 year ago

picklelo commented 1 year ago

We may be able to use api routes to forward requests to the FastAPI server. See: https://github.com/pynecone-io/pynecone/discussions/120

matt-grain commented 1 year ago

As it looks like there is only 2 APIs: /event and /ping to forward requests to, I guess that's not too complicated. But as right now you generate the next.js static website (which is not compatible with api routes), the way to run the frontend will be a little different.

If I can help or test, tell me!

picklelo commented 1 year ago

Ah I see, so the api routes may only work in dev mode, where we don’t do the static site generation.

If you have time and want to try to add this soon, I can help give guidance. Otherwise, we will definitely try to include this in an upcoming milestone.

matt-grain commented 1 year ago

I won't say at all that I'm a next.js expert (else I would probably not use Pynecode.io :D) but I played a little with next.js serverside capabilities, so yes I'll post here some examples, resources or whatever with pleasure. But in brief, yes it means to do not export the static website but to run a node.js server.

picklelo commented 1 year ago

Awesome, I'll look into it too, I'm adding it to the next milestone

matt-grain commented 1 year ago

Disclaimer

if this is only to decouple the frontend and the python backend, using next.js serverside capability is probably overkill. I'm pretty sure that's doable using nginx and some good url redirection (to redirect calls from /api:3000 to /api:8000).

But, if you start to use next.js server side capabilities, I guess it will simplify your python to typescript engine and you will be able to generate typescript on the fly (thru next.js SSR) as the frontend won`t be static anymore.

So, a little early to say but I`m pretty sure it will open a lot of cool stuff for pyncone.io :)

Some links I found interesting:

next.js server side capabilities:

next.js API routes concept:

Deployment:

Side topic but somewhat linked: BFF

FHU-yezi commented 1 year ago

Needn't to host frontend with Node.js at all, just export static files and host it by Nginx.

matt-grain commented 1 year ago

To be challenged:

Using next.js API routes and other SSR capabilities:

Pros Cons
Hide the FastAPI backend / avoid CORS issues Requires a node.js (or equivalent) server to implement the API routes
Supports SSR and dynamic generation of HTML/JS content based on python code Somewhat redudant with the FastAPI api dedicated to the frontend communication
Simplify future auth needs required at the frontend layer using NextAuth.js Creates a dependence on next.js server side
Possible performance improvement by providing caching when accessing the FastAPI backend may be not needed One more layer, performance impact?

Using nginx to proxify FastAPI:

Pros Cons
Pretty proven and standard Limited to API proxification, no other values
Light Cannot support next.js server-side capabilities
picklelo commented 1 year ago

@matt-grain awesome writeup!

I didn't know about NextAuth.js that looks interesting - we're trying to add some sort of auth into Pynecone soon. In the upcoming release, we're moving to use Websockets for communication, I'm not sure how that will affect things. I think we won't see much benefit from the API caching after this change.

The solution we're planning to use for pc deploy is similar to the second way:

This seems to work pretty well, you can use NGINX or anything to serve the frontend. You just have to make sure the backend url is compiled into the code, so it connects to the correct server for sending events.

picklelo commented 1 year ago

We're using websockets now, so I don't think we can do this. We can re-open this if people want it and there is a good workaround.

zalo commented 1 year ago

Though it's late, I wanted to mention one of the nice benefits of single-port exposure is there's a simple 1-liner for exposing a local app to the internet for development (via flask-cloudflared):

import flask_cloudflared; ext_url = flask_cloudflared._run_cloudflared(port=8000); print(f" * Running on {ext_url}")

Though, perhaps multiple tunnels could be started (with unique URLs for each port); is there a way to tell Pynecone's Frontend to use different URLs for each port?

Alternatively, integrating the TryCloudflared option into Pynecone (for development servers) would be amazing!

EDIT: It seems like TryCloudflared also exposes websocket ports, even if it it's not explicitly marked...