├── .Rbuildignore
├── .gitignore
├── DESCRIPTION
├── NAMESPACE
├── R
├── namespace.R
├── plot.R
└── shiny.R
├── README.md
├── app.R
├── man
└── my_app.Rd
└── tests
├── testthat.R
└── testthat
└── test-example.R
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | # The app.R file is not needed for the package. Only for the remote Shiny app on the server.
2 | ^app.R
3 |
4 |
5 |
6 | #####################################################################
7 |
8 | # Git and GitHub
9 | .git
10 | .gitignore
11 | README.md
12 |
13 | # For Mac users
14 | .DS_Store
15 |
16 | # History files
17 | .Rhistory
18 | .Rapp.history
19 |
20 | # Session Data files
21 | .RData
22 |
23 | # Output files from R CMD build
24 | /*.tar.gz
25 |
26 | # Output files from R CMD check
27 | /*.Rcheck/
28 |
29 | # RStudio files
30 | .Rproj.user/
31 |
32 | # produced vignettes
33 | vignettes/*.html
34 | vignettes/*.pdf
35 |
36 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
37 | .httr-oauth
38 |
39 | # knitr and R markdown default cache directories
40 | /*_cache/
41 | /cache/
42 |
43 | # Temporary files created by R markdown
44 | /*.utf8.md
45 | /*.knit.md
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
3 | # History files
4 | .Rhistory
5 | .Rapp.history
6 |
7 | # Session Data files
8 | .RData
9 |
10 | # Example code in package build process
11 | *-Ex.R
12 |
13 | # Output files from R CMD build
14 | /*.tar.gz
15 |
16 | # Output files from R CMD check
17 | /*.Rcheck/
18 |
19 | # RStudio files
20 | .Rproj.user/
21 |
22 | # produced vignettes
23 | vignettes/*.html
24 | vignettes/*.pdf
25 |
26 | # OAuth2 token, see https://github.com/hadley/httr/releases/tag/v0.3
27 | .httr-oauth
28 |
29 | # knitr and R markdown default cache directories
30 | /*_cache/
31 | /cache/
32 |
33 | # Temporary files created by R markdown
34 | *.utf8.md
35 | *.knit.md
36 |
--------------------------------------------------------------------------------
/DESCRIPTION:
--------------------------------------------------------------------------------
1 | Package: appPackage
2 | Type: Package
3 | Title: This Shiny App is a Package! This Package is a Shiny App!
4 | Version: 0.0.0.9000
5 | Date: 2016-11-01
6 | Authors@R: person(family = "Landau", given = "William", email =
7 | "will.landau@gmail.com", role = c("aut", "cre"))
8 | Description: This project can either be deployed to a server as a Shiny app or
9 | installed locally as a package that runs the app. Either way, the
10 | functionality is the same.
11 | License: GPL (>=3)
12 | Depends: R (>= 3.0.0)
13 | Imports: shiny
14 | URL: https://github.com/wlandau/appPackage
15 | RoxygenNote: 5.0.1
16 | NeedsCompilation: no
17 | Packaged: 2016-11-01 21:48:32 UTC; landau
18 | Suggests: testthat
19 |
--------------------------------------------------------------------------------
/NAMESPACE:
--------------------------------------------------------------------------------
1 | # Generated by roxygen2: do not edit by hand
2 |
3 | export(my_app)
4 | import(shiny)
5 | importFrom(graphics,hist)
6 | importFrom(stats,rnorm)
7 |
--------------------------------------------------------------------------------
/R/namespace.R:
--------------------------------------------------------------------------------
1 | #' @import shiny
2 | #' @importFrom graphics hist
3 | #' @importFrom stats rnorm
4 | NULL
5 |
--------------------------------------------------------------------------------
/R/plot.R:
--------------------------------------------------------------------------------
1 | my_plot = function(number_observations){
2 | hist(rnorm(number_observations), col = 'darkgray', border = 'white')
3 | }
--------------------------------------------------------------------------------
/R/shiny.R:
--------------------------------------------------------------------------------
1 | my_server <- function(input, output) {
2 | output$distPlot <- renderPlot({
3 | my_plot(input$obs)
4 | })
5 | }
6 |
7 | # Needs to be a function so nested dependencies are lazily loaded.
8 | my_ui <- function(){fluidPage(
9 | sidebarLayout(
10 | sidebarPanel(
11 | sliderInput("obs", "Number of observations:", min = 10, max = 500, value = 100)
12 | ),
13 | mainPanel(plotOutput("distPlot"))
14 | )
15 | )}
16 |
17 | #' @title Function \code{my_app}
18 | #' @description Runs the Shiny app.
19 | #' @export
20 | my_app = function(){
21 | shinyApp(ui = my_ui(), server = my_server)
22 | }
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Do you like the interactivity of [Shiny apps](http://shiny.rstudio.com/)? Do you also like the modularity and [unit testing](http://r-pkgs.had.co.nz/tests.html) of [R packages](http://r-pkgs.had.co.nz/)? Check out this small example to get the best of both worlds.
2 |
3 | # It's a Shiny app!
4 |
5 | The customary [`app.R`](http://shiny.rstudio.com/articles/single-file.html) is in the root directory, so you can launch the project as a Shiny app on a server as is. No package installation is required. Instead, `devtools::load_all()` in `app.R` automatically loads all the required R scripts and data files.
6 |
7 | # It's a package!
8 |
9 | Since `app.R` is listed in [`.Rbuildignore`](http://r-pkgs.had.co.nz/package.html), you can install the package as is.
10 |
11 | ```r
12 | install_github("wlandau/appPackage")
13 | ```
14 |
15 | Then, you can run the Shiny app locally.
16 |
17 | ```r
18 | library(appPackage)
19 | my_app()
20 | ```
21 |
22 | # But what if my app uses compiled code?
23 |
24 | Follow the [CRAN directions](https://cran.r-project.org/doc/manuals/r-release/R-exts.html#System-and-foreign-language-interfaces) to build your package on top of [C](https://en.wikipedia.org/wiki/C_(programming_language)), [Fortran](https://en.wikipedia.org/wiki/Fortran), or whatever [compiled language](https://en.wikipedia.org/wiki/Compiled_language) you're using. Then, all you need is an `app.R` that installs the package on the server and then launches your app with a function call. For this example, the server-side `app.R` would look like this.
25 |
26 | ```r
27 | install_github("wlandau/appPackage")
28 | library(appPackage)
29 | my_app()
30 | ```
31 |
32 | Here, feel free to discard the `app.R` inside the package and remove the `app.R` listing from `.Rbuildignore`.
33 |
34 |
35 | # What of my project gets too big and messy?
36 |
37 | Overambitious projects tend to get bloated, cluttered, and slow, especially when substance and interactivity fall under the same roof. If you do serious computation behind the scenes in xyzShinyApp
, you could encapsulate the hidden core functionality in a separate package: say, xyzEngine
. I used this exact approach in my dissertation project. Package fbseq
processes user input and Monte Carlo output, and fbseqCUDA
actually fits the model given an already-parsed set of instructions.
38 |
39 |
--------------------------------------------------------------------------------
/app.R:
--------------------------------------------------------------------------------
1 | devtools::load_all()
2 | my_app()
3 |
--------------------------------------------------------------------------------
/man/my_app.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/shiny.R
3 | \name{my_app}
4 | \alias{my_app}
5 | \title{Function \code{my_app}}
6 | \usage{
7 | my_app()
8 | }
9 | \description{
10 | Runs the Shiny app.
11 | }
12 |
13 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(appPackage)
3 |
4 | test_check("appPackage")
5 |
--------------------------------------------------------------------------------
/tests/testthat/test-example.R:
--------------------------------------------------------------------------------
1 | context("example")
2 |
3 | test_that("example of a test runs as expected", {
4 | expect_silent(my_plot(5))
5 | unlink("Rplots.pdf")
6 | })
--------------------------------------------------------------------------------