Should you develop your Shiny app as an R package?
At the 2022 Appsilon Shiny Conference we shared our technology <a href="https://appsilon.github.io/rhino/">Rhino</a>. My personal point of view is that <b>it helps you develop a Shiny app like a software engineer, even if you are a data scientist, analyst or specialist in another field</b>. One of the key differences is that when we develop a large Shiny app, we don't structure it as a package. In this article I will explain why this distinction is important to us. <h2>Developing vs distributing an app</h2> Firstly, I want to clarify that I will focus on <b>developing</b> a Shiny app, not <b>the way of distributing it</b>. There are many different methods for distributing a Shiny application, and one of them is compiling your well tested app into an R package so that others can install it from CRAN or Package Manager and run it easily. There is no such limit if you want to develop an app using Rhino, but later compile it as a package. <h2>R User vs Software Engineer mindset</h2> R package structure for development is really a great choice for R users like analysts, scientists and other specialists. Why? <ul><li style="font-weight: 400;" aria-level="1">R package is a well known structure and R users can feel safe and comfortable using it.</li><li style="font-weight: 400;" aria-level="1">R package is fine if most of your code is written in R.</li></ul> However in complex Shiny projects, software engineers will often feel limited. There are a lot of tools that work alongside R: Sass, npm, Python, JavaScript tools, end-to-end testing frameworks, Ansible, Terraform, bash scripts, etc. These tools are not just additions to an R package. They often have their own file structures and development workflows and putting them into an R package structure is not convenient. <h2>How apps are structured and developed in other languages</h2> Let's take a look how software engineers structure their apps in other technologies. <h3>Python - apps are not packages</h3> We have frameworks such as <a href="https://www.djangoproject.com/">Django</a>, <a href="https://streamlit.io/">Streamlit</a> or <a href="https://flask.palletsprojects.com/en/2.1.x/">Flask</a>. None of them are developed as Python libraries (equivalent to R packages). <ul><li style="font-weight: 400;" aria-level="1"><a href="https://github.com/django/djangoproject.com">Example project in Django</a></li><li style="font-weight: 400;" aria-level="1"><a href="https://github.com/streamlit/demo-uber-nyc-pickups">Example project in Streamlit</a></li><li style="font-weight: 400;" aria-level="1"><a href="https://github.com/greyli/todoism">Example project in Flask</a></li></ul> <h3>JavaScript - apps are often packages</h3> In JavaScript we have frameworks like <a href="https://www.meteor.com/">Meteor</a>, <a href="https://svelte.dev/">Svelte</a> or <a href="https://www.gatsbyjs.com/">Gatsby</a>. Many apps are often structured as NPM packages. Here are some examples: <ul><li style="font-weight: 400;" aria-level="1"><a href="https://github.com/meteor/examples/tree/main/tic-tac-toe">Example project in Meteor</a></li><li style="font-weight: 400;" aria-level="1"><a href="https://github.com/sveltejs/realworld">Example project in Svelte</a></li><li style="font-weight: 400;" aria-level="1"><a href="https://github.com/gatsbyjs/tutorial-example">Example project in Gatsby</a></li></ul> Does it mean apps should be developed as packages in other languages? No, it means that the JavaScript community developed a modern way for packaging JS code - a unified way for libraries and apps that support <a href="https://nodejs.dev/learn/the-package-json-guide">very complex web development workflows</a>. R package structure is not designed for this. R packages have been designed for easy sharing of reusable sets of functions. For example <a href="https://en.wikipedia.org/wiki/R_package">Wikipedia definition</a> says that <i>“R packages are extensions to the R statistical programming language”.</i> We can be inspired by JavaScript and NPM. Perhaps Shiny apps deserve their own standard of packaging them? Or maybe the R package format needs refinement? <h2>Limitations of developing a Shiny app as a package</h2><ul><li> Flat files structure. It prevents you from organizing your project into clear, traversable structure. I don't see a reason for flattening files structure when you develop a complex app that requires a lot of modules.</li><li>R CMD check as a testing workflow - This is ok for simple apps, but complex apps need significantly more advanced testing (and not only R code needs testing). Linting, unit testing, end to end, performance testing - there are much better project structures that will support these different use cases.</li><li>Development using an R package structure limits you from thinking about the broader ecosystem of tools available to you. It is a great starting point for those new to Shiny, but soon enough you will notice that Shiny app development is not only about R code. It can be also frontend in React, Python scripts or APIs, infrastructure as a code, data pipelines, data validation workflows, environment settings, docker images and more. It will be hard to maintain all of it as a package, and eventually you will end up wrapping only part of your project as an R package and the rest of it will be outside.</li></ul> <h2>Diversity is good</h2> To sum up, we believe that it is important for software engineers to have a choice. Developer communities benefit from a diversity of options. Implementing a Shiny app as an R package is a good choice for many R users. At Appsilon, in our case studies this approach limits us. This is why we decided to dedicate our time and resources to creating Rhino. Our goal is to collect all best practices and tools in one place, so that it is easier to develop really advanced Shiny apps and share that with the R community. <img class="wp-image-12993 aligncenter" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65b01e2b44295a0f332341bc_drake-yeah.webp" alt="" width="401" height="226" />