rstudio / rmarkdown

Dynamic Documents for R
https://rmarkdown.rstudio.com
GNU General Public License v3.0
2.88k stars 979 forks source link

shiny issue addResourcePath #2184

Open heimschf opened 3 years ago

heimschf commented 3 years ago

I deployed a shiny app that is generated with the package learn, shinydashboard and shiny. Prior to updating rmarkdown to the latest version (before I used version 1.12) everything worked fine.

I obtain the following error when deploying my shiny-app (both locally and in Browser):

Couldn't normalize path in `addResourcePath`, with arguments: `prefix` = 'shinydashboard-0.7.1'; `directoryPath` = ''

Below you find my sessionInfo():

locale:
[1] LC_COLLATE=German_Switzerland.1252  LC_CTYPE=German_Switzerland.1252    LC_MONETARY=German_Switzerland.1252 LC_NUMERIC=C                       
[5] LC_TIME=German_Switzerland.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] DT_0.18              rmarkdown_2.9        forcats_0.5.1        shinydashboard_0.7.1 shiny_1.6.0          dplyr_1.0.7          ggplot2_3.3.5       
[8] e1071_1.7-7          learnr_0.10.1       

loaded via a namespace (and not attached):
 [1] Rcpp_1.0.7        compiler_4.1.0    pillar_1.6.1      later_1.2.0       class_7.3-19      tools_4.1.0       digest_0.6.27     jsonlite_1.7.2   
 [9] evaluate_0.14     lifecycle_1.0.0   tibble_3.1.2      gtable_0.3.0      pkgconfig_2.0.3   rlang_0.4.11      DBI_1.1.1         yaml_2.2.1       
[17] xfun_0.24         fastmap_1.1.0     withr_2.4.2       knitr_1.33        generics_0.1.0    vctrs_0.3.8       htmlwidgets_1.5.3 tidyselect_1.1.1 
[25] rprojroot_2.0.2   grid_4.1.0        glue_1.4.2        R6_2.5.0          fansi_0.5.0       purrr_0.3.4       magrittr_2.0.1    scales_1.1.1     
[33] promises_1.2.0.1  ellipsis_0.3.2    htmltools_0.5.1.1 assertthat_0.2.1  mime_0.11         xtable_1.8-4      colorspace_2.0-2  httpuv_1.6.1     
[41] utf8_1.2.1        proxy_0.4-26      munsell_0.5.0     crayon_1.4.1      markdown_1.1     

You find a minimal working example below, please advise on this issue.

---
title: "Minimal Example"
output: learnr::tutorial
runtime: shiny_prerendered
--- 

```{r setup, include=FALSE}
library(learnr)
#library(manipulate)
#library(manipulateWidget) 
library(e1071)
library(ggplot2)
library("dplyr")
library(shiny)
library(shinydashboard)
library(forcats)
#ev noch zu installieren
library(rmarkdown)
#library(shinyFiles)

library(DT)
#library(shinythemes)

#library(googleLanguageR)
knitr::opts_chunk$set(echo = FALSE)

#gl_auth("www/geocoding-R-df7e8c111682.json")

APP zu deskriptiven Statistiken

#shinythemes::themeSelector()
sidebar <- dashboardSidebar(
  sidebarMenu(
    menuItem("Deskriptive Statistiken", tabName = "deskr")
  )
)

body <- dashboardBody(

)  
dashboardPage(
  dashboardHeader(title = "Deskriptive Statistiken"),
  sidebar, 
  body
)

observeEvent(input$update,{
  updateTextAreaInput(session=session,"vecbox",value = input$eingabe)
})


### Describe the problem in detail
cpsievert commented 3 years ago

Attaching @cderv and @gadenbuie as this might be a rmarkdown/learnr issue

heimschf commented 3 years ago

@cpsievert, @cderv, @gadenbuie many thanks for digging into this. Hope you find a solution, Thanks.

gadenbuie commented 3 years ago

Typically that error indicates that the learnr document needs be re-rendered. The best way to confirm that you've completely re-rendered the document is to click on Clear Prerendered Output in the drop down menu of the Run Document button. Then click run document again to prerender and run the app.

heimschf commented 3 years ago

Thanks for your comment, @gadenbuie , I have tried the proposed procedure using both clear prerendered output and clear knitr cache. But this did not help. Also, I tried to move the .Rmd file in a new folder and renamed it and have re-run again. But the error message from "couldn't normalize path in addresourcepath..." persists, unfortunately.

gadenbuie commented 3 years ago

Okay, well that rules out the easy answer. I wonder if the issue you're seeing is specific to shinydashboard? I'll try to investigate further this week.

heimschf commented 3 years ago

thanks, @gadenbuie , it seems that it is specific to shinydashboard but the error only arises together in use with rmarkdown package, which is imported using the learn package. Using a "single shinydashboard" in a app.R file works without problems.

gadenbuie commented 3 years ago

The other thing you could try is to see if shiny dashboard components work as expected in the runtime: shiny_prerendered context, without learnr. For example in a document with the following YAML frontmatter

---
title: "Minimal Example"
output: html_document
runtime: shiny_prerendered
--- 
heimschf commented 3 years ago

Thanks for the idea, but same result... (same error message)

gadenbuie commented 3 years ago

That's a good data point! Does it also fail (in a regular html_document) if you remove the library(learnr) call?

heimschf commented 3 years ago

sorry I should have mentioned, yes, in addition have also checked this, but still fails...

gadenbuie commented 3 years ago

No worries! That reduces the scope of the problem a bit and indicates that learnr isn't specifically involved. Most likely this is an issue with shinydashboard when used in a shiny prerendered document.

gadenbuie commented 3 years ago

@cpsievert @cderv This is really a problem with shiny prerendered rmarkdown documents. Here's a minimal reprex:

---
title: "Minimal Example"
output: html_document
runtime: shiny_prerendered
--- 

```{r setup, include = FALSE}
library(shinydashboard)
dashboardPage( 
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(),
  title = "Dashboard example"
)

I tracked down the problem to [these lines in `rmarkdown:::shiny_prerendered_html()`](https://github.com/rstudio/rmarkdown/blob/bab481aa016f38a94d08f4c03284e9273804b3d4/R/shiny_prerendered.R#L145-L154). The shinydashboard dependency is included in the prerendered doc

```r
# before L145-L154
str(dependencies[[10]])
List of 11
 $ name      : chr "shinydashboard"
 $ version   : chr "0.7.1"
 $ src       :List of 1
  ..$ file: chr "/Library/Frameworks/R.framework/Versions/3.6/Resources/library/shinydashboard"
 $ meta      : NULL
 $ script    : chr "shinydashboard.min.js"
 $ stylesheet: chr "shinydashboard.css"
 $ head      : NULL
 $ attachment: NULL
 $ package   : chr "shinydashboard"
 $ all_files : logi TRUE
 $ pkgVersion: chr "0.7.1"
 - attr(*, "class")= chr "html_dependency"

but the $src$file is replaced with "", which obviously leads to errors.

# after L145-154
str(dependencies[[10]])
List of 10
 $ name      : chr "shinydashboard"
 $ version   : chr "0.7.1"
 $ src       :List of 1
  ..$ file: chr ""
 $ meta      : NULL
 $ script    : chr "shinydashboard.min.js"
 $ stylesheet: chr "shinydashboard.css"
 $ head      : NULL
 $ attachment: NULL
 $ all_files : logi TRUE
 $ pkgVersion: chr "0.7.1"
 - attr(*, "class")= chr "html_dependency"

The primary cause is a conflation of two things:

Resolving either one could resolve this particular issue. But we may not need to replicate htmltools' package dependency resolution step in rmarkdown since it was added to rmarkdown 5 years ago when the package= argument was just being introduced.

cderv commented 3 years ago

Thanks @gadenbuie !

Based on all this investigation, I'll have a closer look on the rmarkdown side regarding this mechanism. Thanks for looking into this !

cderv commented 3 years ago

Ok I understand now better.

I think this is also a edge case because shinydasboard resources are at the root of the package. When inserting the dependencies into the prerendered HTML, rmarkdown will process the dependencies and add the package field + normalize the src$file relative to the package dir root. THis happens here: https://github.com/rstudio/rmarkdown/blob/bab481aa016f38a94d08f4c03284e9273804b3d4/R/shiny_prerendered.R#L309-L325

However, as the root installed package is used as src$file in shinydashboard, the normalize relative to doesn't work as expected. At least I think so

# what happens
rmarkdown:::normalized_relative_to(system.file(package = "shinydashboard"), system.file(package = "shinydashboard"))
#> [1] "C:/Users/chris/Documents/R/win-library/4.1/shinydashboard"
# this does work
rmarkdown:::normalized_relative_to("a/b", "a/b/c")
#> [1] "c"
# not work as expected
rmarkdown:::normalized_relative_to("a/b", "a/b")
#> [1] "C:/Users/chris/AppData/Local/Temp/Rtmpqev1CI/reprex-df473ab7310-waspy-bunny/a/b"
# what should happen
xfun::relative_path(xfun::normalize_path("a/b"), dir = xfun::normalize_path("a/b"))
#> [1] "."

So we may be able to fix this, by fixing the relative path function. I'll try it.

However, I understand that:

Do you think we should change one of the above ?

cderv commented 3 years ago

So we may be able to fix this, by fixing the relative path function. I'll try it.

As expected, it fixes the above issue. This lives currently in rstudio/rmarkdown@fix/relative-same-dir and can be tested with

pak::pak("rstudio/rmarkdown@fix/relative-same-dir")

Not sure this is the right fix for this. The HTML deps processing still puzzles me (but it is there since years ago for a reason I am sure)

However, it shows once again than file path handling is critical. I'd really like to consider fs for this as maybe it could be more robuste on the long term.

gadenbuie commented 3 years ago

Thanks for the follow up @cderv. I think it's likely that we no longer need the shiny prerendered process to be so hands-on with the html dependencies, but it'd be good to talk through that a bit more. Should we move this issue into rmarkdown?

cderv commented 3 years ago

Should we move this issue into rmarkdown?

Yes we could. I don't have right to do that. @cpsievert ?

I think it's likely that we no longer need the shiny prerendered process to be so hands-on with the html dependencies, but it'd be good to talk through that a bit more

I agree. I think shinydashboard could also use the package argument in htmlDependency now.

cpsievert commented 3 years ago

Seems I don't have permission to transfer either