Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ssr part 2 #9339

Open
wants to merge 113 commits into
base: 5.0-dev
Choose a base branch
from
Open

Ssr part 2 #9339

wants to merge 113 commits into from

Conversation

pngwn
Copy link
Member

@pngwn pngwn commented Sep 12, 2024

Description

Please include a concise summary, in clear English, of the changes in this pull request. If it closes an issue, please mention it here.

Closes: #(issue)

🎯 PRs Should Target Issues

Before your create a PR, please check to see if there is an existing issue for this change. If not, please create an issue before you create this PR, unless the fix is very small.

Not adhering to this guideline will result in the PR being closed.

Tests

  1. PRs will only be merged if tests pass on CI. To run the tests locally, please set up your Gradio environment locally and run the tests: bash scripts/run_all_tests.sh

  2. You may need to run the linters: bash scripts/format_backend.sh and bash scripts/format_frontend.sh

gradio/blocks.py Outdated
self.node_port = None

if not Blocks.node_process:
(node_server_name, node_process, node_port) = start_node_server(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than starting node in init, we can do in startup_events method of gr.Blocks. That way, if you're nesting multiple blocks in a single app, only one node process is started.

And startup_events runs even when mounted in a larger FastAPI app.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I think we're only going to start one node process anyways with this implementation since we're attaching it to the class but I still think startup_events is a bit cleaner.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah @abidlabs suggested that but we can't do it there if i remember from my testing because we need to know certain details before mounting the gradio app.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Happy to change it in another PR if i'm wrong, i just don't have time to test it atm, the process does only start once tho.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think i might be wrong actually but I'd need to test

@abidlabs
Copy link
Member

(3) It seems that port 7860 is hardcoded somewhere. If a Gradio app is already running on port 7860, its frontend will be shown on the page, even if the new Gradio app that you launched is running on port 7861, etc.

This is now resolved, nice @pngwn!

@abidlabs
Copy link
Member

abidlabs commented Sep 19, 2024

Btw two quick suggestions for the DX:

(1) I highly recommend renaming spa_mode to ssr_mode (and of course, inverting the default value). We're going to be publicizing "server-side rendering", and so users will be looking for an "ssr"-related parameter, it'd be good to use a single term throughout. It also is more intuitive that the default value is False, and a developer needs to set it to True to enable SSR.

(2) I think its far more intuitive for this parameter to live in launch(). I believe the reason we didn't add it there was in the case a developer is mounting a Gradio app to another FastAPI app, but we can add this parameter to mount_gradio_app as well, as we've done with other parameters.


print("Unable to find node install path, falling back to SPA mode.")
print(
"If you wish to use the node backend, please install node 18 and/ or set the path with the GRADIO_NODE_PATH environment variable."
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have node 20 installed and ssr works. Should this print statement be modified or are we lucky that it works with node 20?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should change it to 18+

Copy link
Collaborator

@freddyaboulton freddyaboulton left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pngwn awesome PR!

Left a couple of suggestions but will keep on testing. Bigger comments though:

SSR seems to apply different styles than non-ssr mode. For example the Error toast takes up the whole width:
error_large

And here is a side-by-side of the same app in ssr and non-ssr mode

SSR
image

Non-ssr
image

Everything is stretched out horizontally.

Additionally, SSR mode does not respect my dark mode system setting and it does not respect the ?__theme query parameter either.


node_process = subprocess.Popen(
[node_path, SSR_APP_PATH],
# stdout=subprocess.PIPE,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: delete

gradio/routes.py Outdated
node_port: int,
python_port: int,
) -> Response:
client = httpx.AsyncClient()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can create one client at the top level of the file and re-use it. It may even be better performance as it will use http connection pooling: https://www.python-httpx.org/advanced/clients/

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried that but it was erroring that i can't use a closed client or something.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh wait thats because of the with usage, if i change that, it will work.

@yvrjsharma
Copy link
Collaborator

TYSM @pngwn, I can now confirm that I am able to build multiple demos successfully on the Windows machine, both with and without specifying spa_mode=False. Absolute legend!

@pngwn
Copy link
Member Author

pngwn commented Sep 19, 2024

Regarding 2, I'm not sure if we can. I think we create the app really early on and I need to know whether to attach the middleware when we create the app but I'll check.

@abidlabs
Copy link
Member

abidlabs commented Sep 20, 2024

Let me see if I can put together a PR with my suggestions

Edit: PR ready here: #9399

@abidlabs
Copy link
Member

abidlabs commented Sep 20, 2024

Fixing the issue around share links is more interesting. It appears to be a CORS issue since access to localhost links is blocked from external links, including gradio.live links, which would be an easy fix. But I actually think there's a deeper issue, which is that xxxx.gradio.live links are trying to fetch the config from a user's localhost url instead of using the relative xxxx.gradio.live/config url. Happy to sync with you on this afterwards @pngwn but I don't think its a blocker for the beta release

@pngwn
Copy link
Member Author

pngwn commented Sep 20, 2024

Ah. The app just uses whatever the 'api' is listed as to get those links. Can sync later.

@abidlabs
Copy link
Member

Python unit tests should be passing now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants