Rhino 1.7.0 Update on CRAN: Improved Linting and Automatic Reloading

Estimated time:

It’s been almost a month since the last release of our framework for enterprise Shiny applications, so it’s time for <a href="https://cran.r-project.org/web/packages/rhino/index.html" target="_blank" rel="noopener"><strong>Rhino 1.7</strong></a>! This version comes with new rules for the R linter, more consistent loading behavior, and automatic app reloading during development. Read on for the details!
<blockquote>Curious about building enterprise-grade Shiny apps with Rhino? <a href="https://appsilon.com/rhino-r-package-tutorial/" target="_blank" rel="noopener">Discover how with our detailed tutorial.</a></blockquote>
<h3>Table of Contents</h3><ul>  <li><strong><a href="#improved-linting-with-rhino-1-7">Improved Linting with Rhino 1.7</a></strong></li>  <li><strong><a href="#refactored-rhino-app">Refactored rhino::app()</a></strong></li>  <li><strong><a href="#automatic-reloading-with-rhino">Automatic Reloading with Rhino</a></strong></li>  <li><strong><a href="#install-latest-version">How to Install the Latest Version of Rhino</a></strong></li>  <li><strong><a href="#rhinoverse">Rhinoverse</a></strong></li>  <li><strong><a href="#conclusion">Conclusion</a></strong></li></ul>

<hr />

<h2 id="improved-linting-with-rhino-1-7">Improved Linting with Rhino 1.7</h2>
<a href="https://appsilon.github.io/rhino/" target="_blank" rel="noopener">Rhino</a> puts a strong emphasis on code quality. It supports your efforts in this area by providing you with a thoughtful project structure and powerful development tools like linters, which can ensure a consistent style of your code and detect potential problems.

Rhino 1.7 introduces several new rules for <a href="https://appsilon.github.io/rhino/reference/lint_r.html" target="_blank" rel="noopener">rhino::lint_r()</a>. These rules are designed to support the best practices for <a href="https://appsilon.github.io/rhino/articles/explanation/box-modules.html" target="_blank" rel="noopener">using {box}</a>, our tool of choice for structuring your project:
<ul>  <li><strong>Explicitness:</strong> Don’t import all names with <code>module[...] syntax</code>. This pattern makes it difficult to understand how modules are used and can lead to name clashes (<a href="https://appsilon.github.io/rhino/articles/explanation/rhino-style-guide.html#explicit-import">example</a>).</li>  <li><strong>Import sections:</strong> Use separate import statements for packages and modules. This makes it easier to understand the dependencies and structure of your project.</li>  <li><strong>Import limit:</strong> Don’t import more than 8 names from a single module - use the <code>module$name</code> syntax instead. This makes it easier to read and maintain the import statements.</li>  <li><strong>Trailing commas:</strong> Use trailing commas in the import statements. This simplifies adding and reordering lines.</li></ul>
You can read more about these rules in our <a href="https://appsilon.github.io/rhino/articles/explanation/rhino-style-guide.html" target="_blank" rel="noopener">Rhino Style Guide</a>.
<blockquote>Interested in learning more about Rhino? <a href="https://events.ringcentral.com/events/shiny-gathering-11-b3775827-5b59-4068-ab59-82d9a262b7f0" target="_blank" rel="noopener">Sign up for Shiny Gatherings #11 with Kamil Żyła on the 27th February at 6pm CET to explore the latest developments in Rhino. </a></blockquote>
<h2 id="refactored-rhino-app">Refactored <code>rhino::app()</code></h2>
Rhino promotes a unified approach to structuring your application using <code>{box}</code> and Shiny modules. Even the top-level UI and server are defined this way. This uniform structure improves readability and simplifies refactoring.

<a href="https://shiny.posit.co/" target="_blank" rel="noopener noreferrer">Vanilla Shiny</a> gives you more leeway in this area. For example, you can define your UI in any of the following ways:
<pre><code class="language-r">
ui &lt;- titlePanel("Hello!")
ui &lt;- function() titlePanel("Hello!")
ui &lt;- function(request) titlePanel("Hello!")
This flexibility comes in handy sometimes. For example, you might want to process the request parameter, or use a package designed to wrap the entire UI and server of your application. Rhino offers an escape hatch for such use cases - the <a href="https://appsilon.github.io/rhino/reference/app.html#legacy-entrypoint" target="_blank" rel="noopener">legacy entrypoint</a> - but historically, it had some issues.

In Rhino 1.7 we have undertaken a major refactor of rhino::app(). This is mostly an internal improvement, which will provide a solid foundation for future development, but there are benefits for end users too:
<ol>  <li>The app loading and reloading behavior is now more consistent.</li>  <li>When using a legacy entrypoint, any UI or server definition accepted by vanilla Shiny should work with Rhino as well.</li></ol>
<h2 id="automatic-reloading-with-rhino">Automatic Reloading with Rhino</h2>
You can build interactive web applications extremely fast with Shiny, thanks to its powerful reactivity system and a wide variety of available components. Rhino helps you to maintain this high speed of development in the long term by supporting you in applying the <a href="https://appsilon.com/rhino-r-software-engineering/" target="_blank" rel="noopener">best software engineering practices</a>.

Rhino 1.7 takes another step to speed up development and to make it more convenient. The refactor described in the previous section has paved the way for supporting automatic app reloading. To enable it, simply set the <code>shiny.autoreload</code> option for the R session where you’re running your application:
<pre><code class="language-r">
options(shiny.autoreload = TRUE)
Your application will now be reloaded automatically whenever any changes are detected in the source files!

<video width="100%" height="auto" src="https://wordpress.appsilon.com/wp-content/uploads/2024/02/rhino-auto-reload.webm" loop="true" autoplay="true" controls="true"></video>

Please remember that this setting should only be used in development. You can read more about automatic reloading in <a href="https://shiny.posit.co/r/reference/shiny/0.14.2/shiny-options.html" target="_blank" rel="noopener noreferrer">shiny-options</a>.

<strong>Note:</strong> You have to use <code>shiny::runApp()</code> for the autoreload to work - using <code>rhino::app()</code> won't work. For context, see issue <a href="https://github.com/rstudio/shiny/issues/3964" target="_blank" rel="noopener">#3964 in Shiny</a>.
<h2 id="install-latest-version">How to Install the Latest Version of Rhino</h2>
Try out the new features today! You can grab the latest version from CRAN by running:
<pre><code class="language-r">
To migrate your existing Rhino project, check out the <a href="https://appsilon.github.io/rhino/articles/how-to/migrate-1-7.html" target="_blank" rel="noopener">Rhino 1.7 Migration Guide</a>.
<h2 id="rhinoverse">Rhinoverse</h2>
Rhino can be a solid foundation for your Shiny application, but it doesn’t end there. Rhino is the centerpiece of a larger ecosystem - Rhinoverse, a family of open-source R packages created by <a href="https://appsilon.com/" target="_blank" rel="noopener">Appsilon</a> to address the needs of modern web development.

Make sure to check out the other members of the family on <a href="https://rhinoverse.dev/#rhino" target="_blank" rel="noopener">rhinoverse.dev</a>!

<hr />

<h2 id="conclusion">Conclusion</h2>
With improved linting rules, a streamlined app structure, and the introduction of automatic reloading, developers now have even more tools at their disposal to ensure code quality, enhance productivity, and maintain the agility required for rapid iteration.

Upgrade to Rhino 1.7 today, and join us at <strong><a href="https://www.shinyconf.com/shiny-gatherings" target="_blank" rel="noopener">Shiny Gatherings #11 to explore new developments in Rhino</a></strong>.
<blockquote>Interested in taking your R/Shiny skills to the next level? <a href="https://explore.appsilon.com/workshop?utm_medium=referral&amp;utm_source=blog&amp;utm_campaign=levelup" target="_blank" rel="noopener">Download our free ebook today to explore advanced topics such as best practices for software development and integrating user analytics into your Shiny apps. </a></blockquote>

<a href="https://explore.appsilon.com/workshop?utm_medium=referral&amp;utm_source=blog&amp;utm_campaign=levelup"><img class="aligncenter size-full wp-image-23154" src="https://webflow-prod-assets.s3.amazonaws.com/6525256482c9e9a06c7a9d3c%2F65e9e6279f041da2b2645342_572728fc_Banner_Ebook.webp" alt="" width="1070" height="447" /></a>

Contact us!
Damian's Avatar
Damian Rodziewicz
Head of Sales
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.
Have questions or insights?
Engage with experts, share ideas and take your data journey to the next level!
Join Slack

Take Your Business Further with Custom
Data Solutions

Unlock the full potential of your enterprise with our data services, tailored to the unique needs of Fortune 500 companies. Elevate your strategy—connect with us today!

open source