ThinkR-open / golem

A Framework for Building Robust Shiny Apps
https://thinkr-open.github.io/golem/
Other
915 stars 133 forks source link

Nested folders inside `www`, `add_resource_path` works locally but not on shinyapps.io deployment. #870

Closed yogat3ch closed 2 years ago

yogat3ch commented 2 years ago

Hi @ColinFay, We're getting comfortable using golem for all of major Shiny apps and really love the framework. However, we still run into puzzling deployment issues like this one from time to time. I've been perusing around for related issues for a while and the only clue I came across was this comment?

We have a golem that uses some images for icons that are updated when they become "active". We accomplished this with html/css:

<img class="tab-assumptions>
.tab-assumptions {
    content: url("/img/inactive/assumptions.svg");
}
.active .tab-assumptions {
    content: url("/img/active/assumptions.svg");
}

As you can see, we use a nested folder structure inside of www since the app has a lot of dependencies and we want to keep them organized. We've added the resource path in golem_add_external_resources as follows:

golem::add_resource_path(
    'img', app_sys('app/www/img')
  )

This works great locally.

However, when deploying remotely the images are broken links. I looked at the Source pane in Chrome Devtools and inside the www folder there's just a single image (unrelated) and the folders with the images (img) are not listed. I've tried altering the paths on the development app to every possible combination "inst/app/www/img/active/", "www/img/active", "img/active" and each of these with a leading /. I've added the images directly to the app with display:none; to try to force inclusion of the dependencies. I downloaded the app image from shinyapps.io and verified that the files were indeed bundled with the deployment image.

Has anyone encountered this before and found a solution?

Working on a reproducible example app to follow

sessionInfo() ``` R version 4.1.3 (2022-03-10) Platform: aarch64-apple-darwin20 (64-bit) Running under: macOS Monterey 12.4 Matrix products: default LAPACK: /Library/Frameworks/R.framework/Versions/4.1-arm64/Resources/lib/libRlapack.dylib locale: [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8 attached base packages: [1] stats graphics grDevices datasets utils methods base other attached packages: [1] shiny_1.7.1 crsspierViz_0.0.0.9002 loaded via a namespace (and not attached): [1] fs_1.5.2 reactable_0.2.3 usethis_2.1.6 fontawesome_0.2.2 [5] lubridate_1.8.0 devtools_2.4.3 rprojroot_2.0.3 bslib_0.3.1 [9] tools_4.1.3 tippy_1.0.0 utf8_1.2.2 R6_2.5.1 [13] DBI_1.1.2 colorspace_2.0-3 withr_2.5.0 tidyselect_1.1.2 [17] prettyunits_1.1.1 processx_3.5.3 RMySQL_0.10.23 leaflet_2.1.1 [21] curl_4.3.2 compiler_4.1.3 cli_3.3.0 xml2_1.3.3 [25] desc_1.4.1 sass_0.4.1 scales_1.2.0 bs4Dash_2.0.4.9000 [29] callr_3.7.0 askpass_1.1 commonmark_1.8.0 crssDB_0.0.0.9201 [33] stringr_1.4.0 digest_0.6.29 pkgconfig_2.0.3 htmltools_0.5.2 [37] sessioninfo_1.2.2 attempt_0.3.1 dbplyr_2.1.1 fastmap_1.1.0 [41] htmlwidgets_1.5.4 rlang_1.0.2 rstudioapi_0.13 jquerylib_0.1.4 [45] generics_0.1.2 jsonlite_1.8.0 crosstalk_1.2.0 dplyr_1.0.9 [49] config_0.3.1 googlesheets4_1.0.0 magrittr_2.0.3 Rcpp_1.0.8.3 [53] munsell_0.5.0 fansi_1.0.3 lifecycle_1.0.1 whisker_0.4 [57] stringi_1.7.6 yaml_2.3.5 brio_1.1.3 pkgbuild_1.3.1 [61] promises_1.2.0.1 crayon_1.5.1 echarts4r_0.4.3 knitr_1.38 [65] ps_1.6.0 pillar_1.7.0 pkgload_1.2.4 glue_1.6.2 [69] packrat_0.8.0 cicerone_1.0.5.9000 golem_0.3.2 pool_0.1.6 [73] remotes_2.4.2 renv_0.14.0 vctrs_0.4.1 httpuv_1.6.5 [77] testthat_3.1.3 cellranger_1.1.0 virgaUtils_0.0.0.9001 openssl_2.0.2 [81] purrr_0.3.4 tidyr_1.2.0 reactR_0.4.4 assertthat_0.2.1 [85] cachem_1.0.6 xfun_0.30 mime_0.12 xtable_1.8-4 [89] roxygen2_7.1.2 UU_0.0.0.9006 later_1.3.0 rsconnect_0.8.26 [93] googledrive_2.0.0 gargle_1.2.0 tibble_3.1.7 memoise_2.0.1 [97] ellipsis_0.3.2 here_1.0.1 ```
yogat3ch commented 2 years ago

Update: A testing repo is up - test_golem. Steps:

  1. Clone the repo
  2. golem::run_dev()
  3. See the image
  4. Open app.R
  5. Deploy to shinyapps.io
  6. Puzzle about why image is gone
ColinFay commented 2 years ago

Thanks for reporting this, I'll dig into that.

FWIW I can reproduce on RStudio Connect too : https://connect.thinkr.fr/content/545/

yogat3ch commented 2 years ago

Thanks @ColinFay! I've submitted a ticket to shinyapps.io to ask about it as well. I'll add any additional info from them when they respond.

yogat3ch commented 2 years ago

Hey @ColinFay, Steve with ShinyApps explained why this issue occurs when deploying which I'll quote below for anyone else who runs into this issue and lands here:

I reviewed this with the shinyapps.io team it looks like a side-effect of Workbench/IDE (and RStudio Connect) which is why you're able to run this app locally.

Under the IDE/Connect, an extra directory tree level (identifying the "worker id" this session is being served) must be added to all URLs in order to reach the application content.

This is made somewhat transparent to html code by the tag injected near the top of the html source returned.

As a result, referencing the image via <img src="img/test/test.png"> still works as expected.

However, since the browser was told that the site's , the file it actually requests from shinyapps.io is "/[worker id]/img/test/test.png".

Unfortunately, it seems that browsers don't consider settings when computing absolute URLs provided in externally loaded CSS.

A few workarounds could be: Specify the image URL as an inline CSS style, e.g. img( style = "content:url('img/test/test.png;')" ). Specify a relative path in custom.css, e.g. content: url("../../img/test/test.png");.

We tried both workarounds and the first doesn't appear to work locally. The second, however, works locally and remotely, so this is the official fix.

Thanks for building such a solid app framework. We love it! Cheers 🎉

VincentGuyader commented 2 years ago

hi, I use this application https://github.com/VincentGuyader/golimg to group the different ways of displaying images with golem (while making sure it can be deployed correctly). When you have found the problem, let me know and I will add the use case in this repository :)

yogat3ch commented 2 years ago

Hi @VincentGuyader, I just updated test_golem with the fix as described above for showing an image via the background-image CSS attribute. This allows for images to be dynamically changed out via state change (hover/active/focus etc) without JS. Useful for menu items.

Specify a relative path in custom.css, e.g. content: url("../../img/test/test.png");.

I think the repo should provide everything you need to update golimg. Let me know if you have any questions!