Recreating the Shiny App tutorial with a Plumber API + React: Part 3
This is part two of our three part series
- Part 1: Recreating the Shiny App tutorial with a Plumber API + React: Part 1
- Part 2: Recreating the Shiny App tutorial with a Plumber API + React: Part 2
- Part 3: Recreating the Shiny App tutorial with a Plumber API + React: Part 3 (this post)
So far, we have seen how to create an app using ReactJS and and a Plumber API. In part 3, we will show you how to host the application on RStudio Connect (RSC)!
When it comes to hosting the application on RSC we will set the content URL for both the app and API so that they are in the same domain and won’t have this CORS issue.
https://{YOUR_CONNECT_SERVER_HERE}/stf/api/
https://{YOUR_CONNECT_SERVER_HERE}/stf/app/
Both apps will be a subdomain of
https://{YOUR_CONNECT_SERVER_HERE}/stf/
Preparing the Build for RStudio Connect
To prepare the build for RStudio Connect we can do a couple of things we need to add to make it deployable.
The public/
folder in React is great for storing static assets such as images, fonts, and JS files. It is located within the app/
directory. Any files placed in this folder will be copied into the build folder when you run the build script. This is useful if you need to reference a file in your code that is not JavaScript, such as an image. For example, if you have an image named logo.png
in your public folder, you would reference it in your code like this: /logo.png
. It’s important to note that the public
folder is only for static assets.
The public folder contains the HTML which can be changed to set things like the page title. The <script>
tag with the compiled code will be added to it automatically during the build process. In index.html you might notice that there are links to various files from the public folder.
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" crossOrigin="use-credentials"/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
In the above code the %PUBLIC_URL%
is a variable that contains the URL to the public folder of the application. Missing files will not be called at compilation time, and will cause 404 errors at runtime. If this %PUBLIC_URL%
variable is incorrect then we will receive 404 errors when accessing the deployed build.
The next minor issue is that we are using a hardcoded URL for our API. When developing locally we probably want to use the locally hosted URL e.g localhost:8000
. When we deploy both the API and app to RSC, we want to change this to be the URL of our production API which we will know once we’ve deployed it to RSC.
We can extract these values out into environment variables that can change between development and production environments. We do this by creating two files .env.production
and .env.development
in the root directory of the app.
Within the .env.development
we can add
PUBLIC_URL=localhost:3000
REACT_APP_PUBLIC_API_URL=localhost:8000
Within .env.production
we need to add the URL of the RStudio Connect platform that we are deploying to. In RSC you can also set content URL for your content. We’re going to set these variables to be the content urls we will set later when deploying to RSC
PUBLIC_URL=https://{YOUR_CONNECT_SERVER_HERE}/stf/api/
REACT_APP_PUBLIC_API_URL=https://{YOUR_CONNECT_SERVER_HERE}/stf/react/
Within the App.js
file we need to change the onSliderChange()
function to use this newly defined REACT_APP_PUBLIC_API_URL
envrionment variable
async onSliderChange(input) {
var apiURL = process.env.REACT_APP_PUBLIC_API_URL;
await axios.get(`${apiURL}`, {
params: {
bins: input,
}
}).then((data) => {
this.setState({
rawdata: [
{
y: data.data.map(x => x["counts"]),
x: data.data.map(x => x["mids"]),
type: 'bar'
}
]
})
});
}
Building the Application
From our application folder we want to run the following to create a production build for our React Application
npm run-script build
The build process in React is responsible for converting the source code into a form that can be executed by the browser. This process includes several steps, such as transpiling, bundling, and optimization.
During transpilation, the source code is converted from one format to another. For example, it can be converted from JSX to JavaScript. This step is necessary because browsers cannot understand JSX directly.
After transpilation, the code is bundled into static minified files. Bundling helps to reduce the size of the code and make it more efficient to load.
Finally, the code is optimized for performance. This may include minification, which reduces the size of the code, and dead code elimination, which removes unused code from the bundle. By optimizing the code, the build aims to run quickly and efficiently in the browser.
The Manifest File
To deploy content to RStudio Connect a manifest.json file is required. A manifest file for RStudio Connect is a list of the files that need to be deployed in order for content to run. This list includes both the source code files and any dependencies that are required. The manifest file ensures that all of the necessary files are included in the deployment, and it also provides a way to specify the order in which the files should be deployed. This is important because some files may need to be deployed before others in order for everything to work correctly. The manifest file is typically named manifest.json
and it is placed in the same directory as the rest of the files that need to be deployed.
We can create a manifest file with the {rsconnect} R package.
The rsconnect R package
The {rsconnect} R package makes it easy to deploy R code and other applications such as our React app to RStudio Connect. You can get your code up and running on RSC with minimal configuration in just a few simple steps. All you need is an RSC server and an account with privileges to deploy content.
If we haven’t installed the package we can install it with install.packages("rsconnect")
from within an R session.
You will then need to register your RStudio Connect user to the package by specifying your account name and server URL
library("rsconnect")
rsconnect::addConnectServer("https://myserveraddress:3939", "myserver")
rsconnect::connectUser(server = "myserver")
The {rsconnect} server name, myserver
, is an arbitrary name that is used to identify an RSC server when using {rsconnect}. You can choose any name you wish.
The output of this command will prompt you with a link to your RSC server asking you to authenticate.
We need to create manifest files for both the app build directory and the API directory. We can do this via rsconnect::writeManifest(appDir = 'path/to/app/build/')
you can specify the path to the directory with the appDir
argument. The default value for the appDir
argument is the current working directory, so if you start the R session in a directory we need to write a manifest for, then there is no need to specify any arguments, e.g rsconnect::writeManifest()
.
Once both manifests are created we can use the following functions to deploy the app and API
library("rsconnect")
rsconnect::deployApp(
appDir = 'path/to/api/directory'
appName = 'Static Faithful API',
server = 'myserver')
rsconnect::deployApp(
appDir = 'path/to/app/directory'
appName = 'Static Faithful App',
server = 'myserver')
The output of this function will prompt links to your deployed content. From there you can set the content URL.
Content URL
The final step to avoid CORS problems is to set both the app’s and API’s content URL. This may be accomplished by opening the settings symbol, then clicking the Access tab. There will be a Content URL entry at the bottom of the sidebar.
We want to set these to be the same as the URLs we chose for the environment variables in .env.production
, if you’ve been following the tutorial these would be as follows
https://{YOUR_CONNECT_SERVER_HERE}/stf/api/
https://{YOUR_CONNECT_SERVER_HERE}/stf/react/
Final Words
You should be finished if everything is operating as planned, which means you’ll have your app deployed on RStudio Connect. If you’ve made it this far, congratulations! It was a lengthy tutorial!
Thanks for following along, we hope you’ve found it helpful and that you’re now intrigued by the possibility of React apps on RStudio Connect.
If you have any questions or feedback, please let us know.