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

[FR] Support simple dynamic runtime without shiny #2232

Closed
dipterix opened this issue Oct 13, 2021 · 11 comments
Closed

[FR] Support simple dynamic runtime without shiny #2232

dipterix opened this issue Oct 13, 2021 · 11 comments
Labels
question general questions - not an issue RStudio IDE concerns the rstudio ide

Comments

@dipterix
Copy link

dipterix commented Oct 13, 2021

Current rmarkdown::render function supports 4 runtime options

$runtime
c("auto", "static", "shiny", "shinyrmd", "shiny_prerendered")

When I was trying to embed some htmlwidgets with no self_contained (large datasets: ~200MB 3D mesh files) under static runtime, the browser gives me CORS error.

So I tried to run the document with shinyrmd and shiny_prerendered, the browser gave me JavaScript errors (basically JS object Shiny was not working as expected). The reason why this happened was because htmlwidgets allowed the widgets to have different behaviors with/without shiny. When the widgets detected shiny, they tried to call shiny input update functions, but since shiny behaved different than the normal dashboard mode, JS error was raised.

Would it be possible to have dynamic runtime, but without shiny?

[PS]: I also tried shiny runtime out of curiosity, but got C Stack error.

@cderv
Copy link
Collaborator

cderv commented Oct 18, 2021

Hi,

Can you share a reproducible example of what you mean by dynamic runtime without shiny ?

I am not quite sure to follow what you tried. htmlwidgets can often be used inside plain HTML documents without a shiny backend. It is most often JS and CSS. when self contained, everything is embeded but when not self contained, the resources will need to be loaded when served. You can have CORS error in your browser depending on how you serve maybe.

Are you opening the document as a file in the browser ? or are you deploying to a server ? Or maybe serve the document locally ? When does the CORS error happens.

That is just rough hints on what I have understand. Please precise dynamic runtime without shiny to that I can give a more precise answer.

Sorry if I misunderstood. Thanks!

@dipterix
Copy link
Author

dipterix commented Oct 18, 2021

Please use the following script to install

install.packages("threeBrain")
threeBrain::download_N27()
threeBrain::merge_brain()

In your rmd file, copy-paste the following code:

brain <- threeBrain::merge_brain()
plot(brain)

In the rendered html, open console, and you will see CORS error.

Remark: the CORS error exists no matter the requested file exists or not. Just want to provide a simple example here.

Reason

The widget used to work fine in static mode. However, since the security fix, most browsers now treat requests to local files with different paths (even sub-directory) as CORS. This patch breaks static htmlwidgets whose self_contained are false.

What's the problem (not really) with shinyrmd runtime?

In shiny, some htmlwidgets behave differently than in static mode. This is because the widgets can detect whether they shiny is present with JavaScript HTMLWidgets.shinyMode and change accordingly. Since shiny in shinyrmd behave slightly different than the normal shiny applications, these widgets often result in failure. From what I have observed, packages like visNetwork and threeBrain fail definitely.

My naive proposal

Render the rmd in static mode, but host a simple server (without shiny) to show the html later. I guess this wouldn't change any existing code.

Although I also request changes in htmlwidgets package, it might be the most easiest to add this new runtime in rmarkdown : )

@cderv
Copy link
Collaborator

cderv commented Oct 18, 2021

Thanks for the clearer example.

CORS can indeed be an issue with some tools when the html file is not properly served. Requests are made to file: instead of http. Serving should fix this.

Render the rmd in static mode, but host a simple server (without shiny) to show the html later.

Do you mean using a local web server ?
you could already serve your file using servr::httd() to open in a local webserver from R.

Does it solves the issue ? I don't see any CORS using this method but it seems that threeBrain writes the JSON file in some place not found by the resulting Rmd file. 🤔

@cderv
Copy link
Collaborator

cderv commented Oct 18, 2021

threeBrain writes the JSON file in some place not found by the resulting Rmd file.

Seems like threebrain looks for the file in lib/ which is hard coded, but it will in fact be in another place. Rmd render supporting files in *_files folder by default, which could be modified by user lib_dir yaml key.

So I believe there is some wrong interaction with the tools maybe currently

@dipterix
Copy link
Author

dipterix commented Oct 18, 2021

Seems like threebrain looks for the file in lib/ which is hard coded, but it will in fact be in another place. Rmd render supporting files in *_files folder by default, which could be modified by user lib_dir yaml key.

Whether the file exists doesn't matter as I have corrected the path but still files cannot be loaded. The issue is for static files, web browsers won't even try to load local files if not in the same path (not even child path).

Do you mean using a local web server ?

Yes. That's exactly what I was thinking about, a local server without shiny.

you could already serve your file using servr::httd() to open in a local webserver from R.

That's right, I'm doing that right now. However, it would be better if we could just click the knit button in RStudio to render the document instead of manually do so (render without output, and then servr::httd())

Here's the result of using servr::httd() to prove that this strategy works.

image

@cderv
Copy link
Collaborator

cderv commented Oct 19, 2021

That is a lot clearer now !

Whether the file exists doesn't matter as I have corrected the path but still files cannot be loaded.

It matters because I can't reproduce the issue on my end using the CRAN version of the threeBrain package. It required me digging through this and tweak you example. It is better if we can reproduce without issue. Otherwise, it is harder to help

it would be better if we could just click the knit button in RStudio to render the document instead of manually do so (render without output, and then servr::httd())

So this would be a feature request in the RStudio IDE so that knitting the file using the button will rneder using rmarkdown::render() then serve the file locally. There would be nothing to do in rmarkdown directly about this.

Currently, the way you are doing it is the right way to do it.

  1. servr::httd() to serve the directory where the Rmd is
  2. rmarkdown::render() the doc and look at the served document

Maybe a helper function could be made to do this in a single step. Some in servr package tries to do this. Maybe something with the Job API in RStudio IDE could be useful.

Anyway, the limitations of Viewer rendering in RStudio IDE after rmarkdown::render() is called. The call to the viewer is done by the IDE itself - not rmarkdown.

Thanks for opening this issue!

@dipterix
Copy link
Author

dipterix commented Oct 20, 2021

It matters because I can't reproduce the issue on my end using the CRAN version of the threeBrain package. It required me digging through this and tweak you example. It is better if we can reproduce without issue. Otherwise, it is harder to help

A lesson learnt. Sorry for the inconvenience, and thanks for explaining to me.

So this would be a feature request in the RStudio IDE

Yes I've filed a feature request in the RStudio IDE. What I'm curious about is how runtime=shiny or runtime=shinyrmd rendered internally? They are not static from what I observe.

Another question is if RStudio IDE decide to add this feature, how would they know when to render in dynamic mode or when to render in static mode? There must be some indicators in the rmd header? (what's a long shot I was asking...)

@cderv
Copy link
Collaborator

cderv commented Oct 20, 2021

What I'm curious about is how runtime=shiny or runtime=shinyrmd rendered internally? They are not static from what I observe.

They use shiny R package to serve the website. At some point it will call shiny::runApp() which will open a shiny server to host the website. It is not just a static website, it is a web app with an R backend.

Another question is if RStudio IDE decide to add this feature, how would they know when to render in dynamic mode or when to render in static mode?

When there is runtime: shiny or runtime: shinyrmd (equivalent to runtime: shiny_prerendered), then it means a shiny server is needed. shiny::runApp() will be used. All the other outputs are static document: HTML, CSS and JS files + some resources.

Unless I am still missing something about what "dynamic" mode (or document) means from you...

@dipterix
Copy link
Author

Gotcha. Thanks!

@cderv cderv added question general questions - not an issue RStudio IDE concerns the rstudio ide labels Oct 25, 2021
@cderv
Copy link
Collaborator

cderv commented Dec 22, 2021

Issue has been open in rstudio/rstudio#9977

I'll close this one here and we'll follow there.

Thanks!

@cderv cderv closed this as completed Dec 22, 2021
@github-actions
Copy link

This old thread has been automatically locked. If you think you have found something related to this, please open a new issue by following the issue guide (https://yihui.org/issue/), and link to this old issue if necessary.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question general questions - not an issue RStudio IDE concerns the rstudio ide
Projects
None yet
Development

No branches or pull requests

2 participants