# install.packages('pak')
::pak('mjfrigaard/shinypak') pak
3 Packages
This chapter covers the necessary ingredients of R packages. We’ll start by exploring the differences between Shiny projects, R packages, and Shiny app-packages. Then, we’ll dive into the requirements for 1) creating new Shiny app-packages, and 2) converting Shiny app projects into Shiny app-packages.
Before we start, we should establish some operational definitions of what is meant by the terms ‘project’, ‘package’, and ‘app-package’.
Shiny Projects
- This book will consider a Shiny app project to be a directory containing a Shiny application (in an
app.R
file orui.R
/server.R
files)
- Shiny projects also include a Posit workbench project file (
.Rproj
)
- This book will consider a Shiny app project to be a directory containing a Shiny application (in an
R Packages
- I’ll use the term R package to describe a directory of functions, documentation, or data that can be successfully installed and loaded into an R session
- An R package includes the necessary dependency management (
NAMESPACE
), metadata files (DESCRIPTION
), Posit workbench project file (.Rproj
), and has access to the package development tools in Posit Workbench
- I’ll use the term R package to describe a directory of functions, documentation, or data that can be successfully installed and loaded into an R session
Shiny app-packages
- A Shiny app-package (which you have probably already guessed) is an R package containing a Shiny application
- Shiny app-packages have all of the functionality of a standard R Package but also contain the files and folders required to successfully develop, run, and deploy a Shiny app
- A Shiny app-package (which you have probably already guessed) is an R package containing a Shiny application
I’ll differentiate Shiny app projects, R packages, and Shiny app-packages using icons
There are multiple reasons for deciding to develop a Shiny app-package, but if you’re reading this book, you’ve likely found yourself in one of two circumstances:
You want to develop a new app, but want it structured as an R package.
You’ve already developed a Shiny app project, but now you need to convert it to a Shiny app-packages
The previous chapters covered a few practices to adopt during development that improve the extensibility of your app and will make it easier to convert into a Shiny app-package.1
3.1 Development Environment
RStudio (developed by Posit, PBC) is a popular integrated development environment (IDE) that streamlines many R package development tasks. I’ve purposely connected RStudio to the definitions above for R package and Shiny app-packages. Specifically, the package development tools provided in the Build pane and the devtools
package.
Posit has recently released a new IDE: Positron.. This IDE is under active development, so most of the chapters will focus on developing Shiny app-packages in the RStudio IDE. Future chapters will include descriptions of Positron if the development process or features are significantly different from RStudio.
Developing R packages in RStudio (or using .Rproj
files) is not required. There are alternative package development tools and processes outside of Posit Workbench, and many developers employ these setups.
Package development outside RStudio would look almost identical to development in the IDE:
Create the package structure (
R/
folder for.R
scripts,man/
folder for documentation,data/
folder for datasets, etc.)Create
DESCRIPTION
andNAMESPACE
files, etc.Ensure the package can be installed and loaded into an R session.
It’s also possible to use many of the development workflow functions we’ll cover here outside of the IDE (roxygen2::roxygenize()
, devtools::check()
, devtools::install()
, etc.).
3.2 R packages
R packages can be easily shared, reused, and reproduced because they all have a familiar structure, and each folder and file plays an essential role in extending R’s capabilities.2
Below is a folder tree with some of the typical files and folders found in R packages:
<R package>/
├── DESCRIPTION
├── <R package>.Rproj
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── NEWS.md
├── README.Rmd
├── README.md
├── renv.lock
├── R/
├── man/
├── tests/
├── data/
├── data-raw/
├── vignettes/
├── inst/
└── renv/
This chapter will cover the minimum requirements for an R package, so you can handle both creating new Shiny app-packages and converting existing Shiny projects into Shiny app-packages.
3.2.1 Functional R packages
If you’ve done some research on R packages, you’ve probably encountered one (or both) of the following statements,
‘RStudio [Posit Workbench] and
devtools
consider any directory containingDESCRIPTION
to be a package’ - R Packages, 2ed (Chapter 9,DESCRIPTION
)‘all a project needs to be a package is a directory of
R/
files and aDESCRIPTION
file.’ - Mastering Shiny (Chapter 20, Packages)
The sap
directory has:
sap/
├── DESCRIPTION
├── sap.Rproj
├── R/
│ ├── mod_scatter_display.R
│ ├── mod_var_input.R
│ └── utils.R
├── README.md
├── app.R
├── movies.RData
└── www/
└── shiny.png
4 directories, 9 files
- 1
-
DESCRIPTION
file
- 2
-
.Rproj
file
- 3
-
R/
folder with.R
files
So, is sap
a functioning R package?
3.2.1.1 Can we load it with devtools
?
Package development kicks off with the load_all()
function from devtools
, which is similar to calling library()
(we’ll cover this function extensively in the devtools
chapter).
However, when we attempt to load the code in the R/
folder with load_all()
, we see the following error:
install.packages("devtools")
library(devtools)
::load_all() devtools
3.2.1.2 Can we use the Build pane?
If you’re using the RStudio IDE, then functioning R packages also have access to the Build pane, which allows us to quickly load, install, and test code.
When we open sap
, the Build pane is not displayed in the IDE:
As we’ve just learned, the presence of the DESCRIPTION
file and an R/
folder are insufficient to turn a Shiny app project into a functioning R package that can be installed and loaded into an R session and has access to the Build pane in the IDE.
“A project needs a
DESCRIPTION
file with specific fields, a directory ofR/
files, and a properly configured.Rproj
file to be a functioning R package.”
Let’s see how each of these requirements work together to convert the contents of sap
from a Shiny project into a Shiny app-package.
3.2.2 Does it have a DESCRIPTION
?
Launch app with the shinypak
package:
launch('03.1_description')
The official R documentation3 lists the following required fields for the DESCRIPTION
in R packages:
The ‘Package’, ‘Version’, ‘License’, ‘Description’, ‘Title’, ‘Author’, and ‘Maintainer’ fields are mandatory.
Below is an example DESCRIPTION
file for our new sap
package with the mandatory fields:4
Package: sap
Title: Shiny App-Packages
Version: 0.0.0.9000
Author: John Smith [aut, cre]
Maintainer: John Smith <John.Smith@email.io>
Description: An R package with a collection of Shiny applications.
License: GPL-3
After adding the mandatory fields to the DESCRIPTION
file, devtools::load_all()
runs without the previous error, but the IDE still doesn’t display the Build pane:
3.3 R Projects
.Rproj
files are plain text files with various settings for the IDE. We were able to run devtools::load_all()
above without the presence of the Build pane because the IDE displays the Build pane after reading the fields in the .Rproj
file.
The quickest way to access the fields in the .Rproj
file is under Tools > Project Options….
3.3.1 R Project options
Tools > Project Options… provide access to the project-level options. For example, fields 2 - 4 are available under General, 5 - 8 affect the Code options, and the final two fields deal with Sweave.
The default settings were created when we selected the Shiny app project from the New Project Wizard in the last chapter.
3.3.2 Build tools
I’ve placed the .Rproj
file from sap
with the example .Rproj
file from R Packages, (2ed) side-by-side so you can compare them below:5
sap.Rproj
file and .Rproj
file in R Packages, 2ed
I’ve circled the fields in the .Rproj
file that illustrate it’s configured to work with an R package. Note that in sap
, the Project build tools are initially set to (None) under Build Tools:
Changing the Project build tools option to Package will set the default Build Tools options:6
The links between the Build Tools options and fields in sap.Rproj
are in the figure below:
BuildType: Package
tells the IDEsap
is an R package and triggers the Build pane.PackageUseDevtools: Yes
links the options in the Build pane to thedevtools
package.The
PackageInstallArgs
are complicated, but I’ve included some information about them in the callout block below (and you can read more in the official R documentation)The fourth option (
PackageRoxygenize
) is available under Generate documentation with Roxygen > Use roxygen to generate:- These options affect the documentation in an R package. To match the example from R Packages, 2ed above, make sure Rd files, Collate field, and NAMESPACE file are selected and click OK.
After clicking OK, the IDE will automatically reboot, and the additional fields will be added to the bottom of the sap.Rproj
:
Launch app with the shinypak
package:
launch('03.2_rproj')
Version: 1.0
RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default
EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8
RnwWeave: Sweave
LaTeX: XeLaTeX
BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
PackageRoxygenize: rd,collate,namespace
3.3.3 The Build pane
When the new session starts, the new project-level options activate the Build pane in the IDE, and I can check the R package functionality by loading the code with Build > Load All
I should see the following in the Console:
ℹ Loading sap
There you have it–sap
is a functional app-package!
3.3.4 Functional app-packages
In a functional app-package :
- The
DESCRIPTION
file contains the seven mandatory fields7, making running the necessarydevtools
functions possible.
- The
.Rproj
file contains the three package configuration fields8, which makes the Build pane accessible and functional.
Think of the two items above as a two-part process: the DESCRIPTION
requires specific fields, and the IDE requires .Rproj
fields to trigger the Build pane.
3.4 App-packages
The Posit documentation lists the following way(s) to create R packages:9
Call
usethis::create_package()
.In Posit Workbench, do File > New Project > New Directory > R Package. This ultimately calls
usethis::create_package()
, so really there’s just one way.
See the 03.3_create-package
branch of sap
.
create_package()
is a great option if you’re looking for a way to quickly create or convert your Shiny project into a Shiny app-package. In the following sections I’ll cover some suggestions for using create_package()
.10
3.4.1 New app-packages
If you haven’t written any code and want to create a new Shiny app-package, create_package()
is the quickest way to get started.
First, install devtools
:
install.packages("devtools")
library(devtools)
devtools
automatically loads usethis
Loading required package: usethis
Assuming your current working directory is where you want your new Shiny app-package, call usethis::create_package()
with the path
argument set to getwd()
::create_package(path = getwd()) usethis
This call launches a series of actions:
First, the active project is set to whatever was given to the
path
argument.✔ Setting active project to 'path/to/newApp'
The
R/
folder andDESCRIPTION/
file are created:✔ Creating 'R/' ✔ Writing 'DESCRIPTION'
The
NAMESPACE
and.Rproj
files are created:✔ Writing 'NAMESPACE' ✔ Writing 'newApp.Rproj'
The
.Rproj
is added to the.Rbuildignore
file, the.Rproj.user
folder is added to the.gitignore
and.Rbuildignore
files.✔ Adding '^newApp\\.Rproj$' to '.Rbuildignore' ✔ Adding '.Rproj.user' to '.gitignore' ✔ Adding '^\\.Rproj\\.user$' to '.Rbuildignore'
A new session is opened from the new
.Rproj
file:✔ Opening 'path/to/newApp/' in new RStudio session
When the new session opens, newApp
has the following contents:
newApp/
├── .Rbuildignore
├── .Rproj.user/
├── .gitignore
├── DESCRIPTION
├── NAMESPACE
├── R/
└── newApp.Rproj
You’re now free to develop newApp
. Store and document any .R
files in the R/
folder, edit the DESCRIPTION
file with details about the application, read through R Packages and Mastering Shiny, and add the Shiny code to complete your Shiny app-package.
3.4.2 Converting a Shiny project
If you already have a Shiny app project that needs to be converted into a Shiny app-package, you can also use create_package(path = getwd())
in your root folder, but I recommend using the following arguments:
3.4.2.1 DESCRIPTION
arguments
fields
: these are arguments passed tousethis::use_description()
. If thefields
argument is empty, a boilerplateDESCRIPTION
file is created (similar to this one).These boilerplate fields in the
DESCRIPTION
work, but I’ve found some of the fields are unnecessary (i.e., I’ve never neededAuthors@R:
orORCID
) and inevitably require revision, so I’d prefer to handle this during the creation process (and remove the risk of forgetting to change it later).All fields should be passed in a
list()
asfield = 'value'
pairs.
::use_description( usethislist(Package = 'sap', Version = '0.0.0.9000', Title = 'Shiny App-Packages', Description = 'An R package with a collection of Shiny applications.', "Authors@R" = NULL, Author = utils::person( given = "John", family = "Smith", role = c("aut", "cre")), Maintainer = utils::person( given = "John", family = "Smith", email = "John.Smith@email.io"), License = "GPL-3"))
A few fields require specially formatted values (see the
utils::person()
examples below).::person("John", "Smith", utilsemail = "John.Smith@email.io", role = c("aut", "cre"))
[1] "John Smith <John.Smith@email.io> [aut, cre]"
Two additional arguments from
use_description()
are passed tocreate_package()
:check_name
: verifies your Shiny app-package name is valid for CRAN, so we can set this toFALSE
(unless you’re planning on submitting to CRAN)roxygen2
: isTRUE
by default and adds the fields required to useroxygen2
(which I won’t cover here because we’ll cover documentation in-depth in a future chapter).
3.4.2.2 IDE arguments
rstudio
: adds the necessary Build Tools fields in the.Rproj
file (leave asTRUE
)open
: can be set toFALSE
because we don’t need RStudio/Posit Workbench to open in a new session
::create_package(
usethispath = getwd(),
fields = list(Package = 'sap',
Version = '0.0.0.9000',
Title = 'Shiny App-Packages',
Description = 'An R package with a collection of Shiny applications.',
"Authors@R" = NULL,
Author = utils::person(
given = "John",
family = "Smith",
email = "John.Smith@email.io",
role = c("aut", "cre")),
Maintainer = utils::person(
given = "John",
family = "Smith",
email = "John.Smith@email.io"),
License = "GPL-3"),
roxygen = TRUE,
check_name = FALSE,
rstudio = TRUE,
open = FALSE)
After running usethis::create_package()
with the arguments above, the IDE will present us with a few prompts to confirm:
Overwrite pre-existing file 'DESCRIPTION'?
Overwrite pre-existing file 'sap.Rproj'?
The Shiny app-package structure is below:
├── DESCRIPTION
├── NAMESPACE
├── R
│ ├── mod_scatter_display.R
│ ├── mod_var_input.R
│ └── utils.R
├── README.md
├── app.R
├── movies.RData
├── sap.Rproj
└── www
└── Shiny.png
3 directories, 10 files
The DESCRIPTION
file (shown below) has a few additional fields (Encoding
, Roxygen
, and RoxygenNote
) we didn’t include when we converted sap
above, but we will cover these in the upcoming chapters.
Package: sap
Title: Shiny App-Packages
Version: 0.0.0.9000
Author: John Smith [aut, cre]
Maintainer: John Smith <John.Smith@email.io>
Description: An R package with a collection of Shiny applications.
License: GPL-3
Encoding: UTF-8
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.3.2
Launch app with the shinypak
package:
launch('03.3_create-package')
Recap
This chapter has covered the mandatory fields in the DESCRIPTION
file and the R package configuration fields in .Rproj
. We also covered creating and converting Shiny app projects using the usethis::create_package()
function.
In the next chapter, I’ll cover how you can quickly Load, Document, and Install your package!
Shiny app project features are covered in Section 2.3 and Section 2.4 of the previous chapter.↩︎
Fortunately, Shiny app-packages don’t require all the files and folders displayed in the folder tree to gain the functionality and benefits of an R package.↩︎
The mandatory fields are covered in Writing R Extensions, ‘The DESCRIPTION file’↩︎
Always leave an empty final line in the
DESCRIPTION
file.↩︎.Rproj
files are covered in the What makes an RStudio Project? section of R Packages (2 ed)↩︎The initial Build Tools settings (i.e., (None)) should help explain the absence of any R package development fields in the
sap.Rproj
when we compared it to the version in R Packages, 2ed (i.e.,BuildType
,PackageUseDevtools
,PackageInstallArgs
, andPackageRoxygenize
).↩︎The mandatory fields
DESCRIPTION
fields are:Package
,Version
,License
,Description
,Title
,Author
, andMaintainer
↩︎The
.Rproj
package configuration fields areBuildType: Package
,PackageUseDevtools: Yes
, andPackageInstallArgs: --no-multiarch --with-keep.source
.↩︎This information comes from the Writing R Packages documentation for Posit Workbench.↩︎
usethis::create_package()
is covered in the ‘Fundamental development workflows’ chapter of R Packages, 2ed↩︎