-
Notifications
You must be signed in to change notification settings - Fork 18
/
shiny-apps.Rmd
173 lines (126 loc) · 6.17 KB
/
shiny-apps.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# Shiny apps {#shiny}
[Shiny apps][shiny-posit] can be submitted to _Bioconductor_ as software packages or as documented and tested functions within packages.
## Code organisation
Shiny apps are divided into two parts:
- User interface (UI)
- Server
Shiny apps submitted to _Bioconductor_ must store the <i class="fab fa-r-project"></i> code for both the UI and server code under the `R/` directory of the package.
The bulk of the package code should _not_ be implemented directly within the `shinyApp()` function call.
Instead, internal package functions should be developed to produce and return individual components of the UI and server sides of the Shiny app.
Shiny apps can also be written using [shiny modules][shiny-modules] to allow for
better code organisation and re-usability.
We recommend the following file naming scheme for source files:
- Place internal functions that create observers -- e.g., `shiny::observeEvent()` -- in files named `observers_*.R`.
Do this both for observers reacting to the Shiny server `input` object, and reactive values stored in lists of reactive values (e.g., `shiny::reactiveValues()`).
- Place internal functions that create UI elements -- e.g., `shiny::checkboxInput()` -- in files named `interface_*.R`.
- Place internal functions that update the Shiny server `output` object in files named `outputs_*.R`.
- Place internal functions that perform miscellaneous processing steps in files named `utils_*.R`.
## Running app
Functions in the package should _return_ Shiny apps, but _not_ launch them.
In other words, the function `shiny::runApp()` should not be found anywhere in the package source code.
Instead, users should be left to call that function, using Shiny app objects returned by the package functions and options that control how the app is run (e.g., `launch.browser = TRUE`).
For instance, the package source code should look as follows:
```{r, eval=FALSE}
build_app <- function(...) {
ui <- .build_ui(...)
server <- .build_server(...)
app <- shinyApp(ui = ui, server = server)
}
```
While the user's code should look as follows:
```{r, eval=FALSE}
app <- build_app(...)
shiny::runApp(app, ...)
```
## Building the package
Packages with `shiny` apps should be built using the standard `R CMD build`
command. The package structure should follow a standard R package structure,
with the Shiny app code stored under the `R/` directory.:
```
MyShinyPackage/
|-- app.R
|-- DESCRIPTION
|-- NAMESPACE
|-- R/
| |-- interface_*.R
| |-- observers_*.R
| |-- outputs_*.R
| |- server_*.R
| └- utils.R
|-- tests/
|-- vignettes/
|-- man/
|-- inst/
[...]
```
An optional `app.R` file can be added to the base directory of the package to
launch the Shiny app using the `shiny::runApp()` or a main shiny app deployment
function.
## Testing
All plain non-reactive functions in the package should be testable using
standard unit testing tools (e.g., `r BiocStyle::CRANpkg("testthat")`).
The use of `# nocov start` and `# nocov end` is allowed to ignore part of the code that cannot be tested using traditional unit tests (e.g., `observeEvent`).
For instance:
```{r, eval=FALSE}
# nocov start
observeEvent(input$example_input, {
# <do something>
})
# nocov end
```
Use files `setup-*.R` in the subdirectory `tests/testthat/` to generate only once objects that are used repeatedly as input for the unit tests.
It is recommended to use the `r BiocStyle::CRANpkg("shinytest2")` package to
test visual and computational aspects of Shiny apps.
## Documentation
Man pages documenting functions that return Shiny apps should use the `interactive()` function to demonstrate usage of the app.
For instance, a typical 'Example' section for such a man page should look as follows:
```{r, eval=FALSE}
library(MyShinyPackage)
app <- build_app(...)
if (interactive()) {
shiny::runApp(app, ...)
}
```
Although optional, we highly recommend documenting internal functions of
packages that contain Shiny apps. We recommend doing so in a way that is visible
to developers but not users:
- If using `r BiocStyle::CRANpkg("roxygen2")`, use the tag `@keywords internal`
in the Roxygen block. This will keep the documentation in the package but
remove it from the help page index. You may want to increase the visibility of
internal documentation by linking to it in other help pages within the package
(e.g., within a "for developers" section).
For example:
```{r, eval=FALSE}
#' @keywords internal
.build_app <- function(...) {
...
}
```
- Alternatively (though less common), prefix the manual pages with `INTERNAL_*`
and add them to `man/.gitignore`.
To set the name of an Rd document, use the `@name` tag in the Roxygen block:
```{r, eval=FALSE}
#' @name INTERNAL_build_app
.build_app <- function(...) {
...
}
```
Additionally, the vignette of a shiny app package might include some screenshots, either generated manually or programmatically.
If generated manually, developers can use tools such as [pngquant](https://pngquant.org/) (available as a command line utility and as a GUI on most systems) to reduce their size (about 70%) without too much loss of quality.
Programmatically generated screenshots can be realized by means of the [Webshot2](https://cran.r-project.org/package=webshot2) package, using the `webshot2::appshot()` function.
## Review
When reviewing a shiny app package, the reviewer should check that the package
follows the guidelines outlined in this document.
We highly recommend that reviewers use the `r BiocStyle::CRANpkg("shinytest2")`
package to test the visual and computational aspects of the Shiny app in
addition to standard unit tests for plain functions.
Reviewers should also check that the package documentation is complete and
accurate, and that the package passes `r BiocStyle::CRANpkg("BiocCheck")` in
addition to `R CMD build` and `check`.
The user experience is very important. Reviewers should ensure that the app is
responsive and that the user interface is intuitive and easy-to-use. The app
should not crash or hang when the user interacts with it.
Errors and warnings should be handled gracefully and should be visible and
intelligible to the user. We recommend using
`r BiocStyle::CRANpkg("shinytoastr")` to display error, warning, and info
messages to the user.