This guide aims to make your application up and running using Rhino as quickly as possible. Lets assume an application has a following structure:
. ├── utils │ ├── foo.R │ └── bar.R ├── www │ ├── main.css │ └── main.js ├── server.R └── ui.R
The migration process should not be affected by the combination of server.R, ui.R, global.R, and app.R files in your application, or lack of thereof.
rhino::init()
The first step is moving all application source files to a new app
directory:
.
└── app
├── utils
│ ├── bar.R
│ └── foo.R
├── www
│ ├── main.css
│ └── main.js
├── server.R
└── ui.R
Once source files are moved, if you have a list of library()
calls put it in dependencies.R
in
the root directory. If you do not have such list, then Rhino will try to create one for you in
initialization step.
.
├── app
│ ├── utils
│ │ ├── bar.R
│ │ └── foo.R
│ ├── www
│ │ ├── main.css
│ │ └── main.js
│ ├── server.R
│ └── ui.R
└── dependencies.R
After doing so, you should be able to run your application using shiny::shinyAppDir("app")
.
If you have used renv in your application, then chances are your active renv session does not have
Rhino installed. To address this either deactivate renv or run renv::install("rhino")
.
Apart from additional files related to renv, the target file structure is no different than the one presented above.
Having your application prepared, you can now run rhino::init()
.
.
├── .github
│ └── workflows
│ └── rhino-test.yml
├── app
│ ├── js
│ │ └── index.js
│ ├── logic
│ │ └── init.R
│ ├── static
│ │ └── favicon.ico
│ ├── styles
│ │ └── main.scss
│ ├── utils
│ │ ├── bar.R
│ │ └── foo.R
│ ├── view
│ │ └── init.R
│ ├── www
│ │ ├── main.css
│ │ └── main.js
│ ├── main.R
│ ├── server.R
│ └── ui.R
├── renv
│ └── ...
├── tests
│ ├── cypress
│ │ ├── e2e
│ │ └── .gitignore
│ ├── testthat
│ │ └── test-main.R
│ └── cypress.json
├── .Rprofile
├── .lintr
├── .renvignore
├── app.R
├── dependencies.R
├── old.Rprofile
├── renv.lock
├── rhino.yml
└── app.Rproj
If you did not use renv before, then Rhino initialized it for you. However, if
you did use renv, then Rhino added necessary dependencies to renv.lock
file.
Your .Rprofile
has been moved to old.Rprofile
. If it contained any relevant
bits (e.g. setting options), then carry it over to .Rprofile
created by
Rhino.
The last step to get started with Rhino is configuring it. A minimal setup that
allows running the application is setting legacy_entrypoint
in rhino.yml
.
To be able to run application immediately set legacy_entrypoint: app_dir
, as
this approach requires no further adjustments to application's structure.
As you adjust adjust your application to fit best practices suggested by Rhino,
you can modify legacy_entrypoint
. Ultimately, when application is fully
migrated to Rhino, legacy_entrypoint
setting can be removed from rhino.yml
.
Refer to Next Steps section to see how to continue improving
your application!
The process described in rhino::init()
documentation, albeit not in great detail.
The first step is to put all app files in the app
directory,
so it can be run with shinyAppDir("app")
.
Practical experience of migrating apps shows that it's a useful step
which quickly lets you verify whether the app still works.
The process can be a bit unintuitive however.
For example, if you already have an app.R
file and ui/server/global in R
subdirectory,
you should still move the whole structure under app
.
In this case you'll end up with app.R
, app/app.R
and ui/server/global in app/R/
.
Having two app.R
files might feel awkward.
In general you use rhino::init()
for migration.
This cannot be done via RStudio GUI.
If you already have .Rprofile
with renv when migrating,
you'll load it and won't have Rhino inside.
You need to run rhino::init()
from a different directory (or perhaps run renv::deactivate()).
Rhino will renv::load() your renv.lock.
In particular it will set your options("repos"
) based on renv.lock
.
What to do when I get "unsatisfied dependencies" during migration?
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.