rhino
rhino copied to clipboard
Auto-reload functionality when there are changes in R, JS, CSS/SCSS files
Motivation
I feel it quite cumbersome to have to manually restart the app when developing an app. Could be there any simple way?
Feature description
Perhaps a rhino::dev()
function to run the app and watch for changes in R, JS, and SCSS/CSS files. Restart the app automatically to reflect any changes.
Implementation ideas
Utilize nodemon
and npm-run-all
nodejs package to achieve this goal. Lately I put this package.json
snippet in app root directory:
{
"private": true,
"scripts": {
"dev": "npm-run-all --parallel build-js:watch build-sass:watch run-rhino",
"run-rhino": "nodemon --exec \"Rscript -e 'shiny::runApp(port = 3838)'\" --signal SIGTERM",
"build-js:watch": "npm --prefix .rhino run build-js -- --watch",
"build-sass:watch": "npm --prefix .rhino run build-sass -- --watch"
},
"nodemonConfig": {
"watch": [
"app/main.R",
"app/logic/",
"app/view/",
"app/static/"
],
"ext": "*"
},
"devDependencies": {
"nodemon": "^3.0.3",
"npm-run-all": "^4.1.5"
}
}
Then run npm install
once. Now I only need to run npm run install
in terminal for my {rhino}
-app development.
I think it's better to optionally put this config into .rhino
directory instead and wrap the npm run dev
into an R function to be accessible from R console.
Impact
This feature will undoubtedly revolutionize the daily work of Shiny developers.
Comments
No response
Perhaps these snippets would do:
- R function to run and watch codebase:
dev <- function() {
withr::with_dir(
".rhino",
{
system2(command = "npm", args = c("run", "dev"))
}
)
}
- Modified
.rhino/package.json
{
"scripts": {
"dev": "npm-run-all --parallel build-js:watch build-sass:watch run-rhino",
"run-rhino": "cd .. && nodemon --exec \"Rscript -e 'shiny::runApp(port = 3838)'\" --signal SIGTERM",
"build-js:watch": "npm run build-js -- --watch",
"build-sass:watch": "npm run build-sass -- --watch",
"build-js": "webpack",
"build-sass": "sass --no-source-map --style=compressed ../app/styles/main.scss:../app/static/css/app.min.css",
"lint-js": "eslint --config .eslintrc.json ../app/js",
"lint-sass": "stylelint ../app/styles",
"run-app": "cd .. && Rscript -e \"shiny::runApp(port = 3333)\"",
"run-cypress": "cypress run --project ../tests",
"open-cypress": "cypress open --project ../tests",
"test-e2e": "start-server-and-test run-app http://localhost:3333 run-cypress",
"test-e2e-interactive": "start-server-and-test run-app http://localhost:3333 open-cypress"
},
"nodemonConfig": {
"watch": [
"../app/main.R",
"../app/logic/",
"../app/view/",
"../app/static/"
],
"ext": "*"
},
"devDependencies": {
"nodemon": "^3.0.3",
"npm-run-all": "^4.1.5",
"@babel/core": "^7.15.5",
"@babel/eslint-parser": "^7.15.4",
"@babel/preset-env": "^7.15.4",
"@babel/preset-react": "^7.22.3",
"babel-loader": "^8.2.2",
"cypress": "^7.6.0",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-import-resolver-webpack": "^0.13.1",
"eslint-plugin-import": "^2.24.2",
"sass": "^1.39.0",
"start-server-and-test": "^1.12.6",
"stylelint": "^13.13.1",
"stylelint-config-standard": "^22.0.0",
"stylelint-scss": "^3.20.1",
"webpack": "^5.52.0",
"webpack-cli": "^4.8.0"
}
}
Thank you so much @aswansyahputra for your proposal! I love that you included a concrete, working idea for implementation. :100: :tada:
It came just at the right time, as we are looking into making shiny.autoreload work with Rhino. It seems to have some benefits compared to restarting the whole R with nodemon
:
- It should be somewhat faster.
- You won't need to manually refresh the app page.
But I do love the idea of using npm-run-all
and having rhino::dev()
. I will be working on it in the following days :slightly_smiling_face:
Thank you for your kind words, @kamilzyla! I'm so delighted to hear your positive feedback.
My team and I are eager to use this feature in the near future, and I'm confident that other R users would also appreciate its addition in {rhino}
. :tada: