Closed
Description
Hey,
Given the following express app:
const app = require('express')()
const { WebR } = require('webr');
(async () => {
globalThis.webR = new WebR();
await globalThis.webR.init();
console.log("webR is ready");
await webR.installPackages(['attempt'])
app.listen(3000, '0.0.0.0', () => {
console.log('http://localhost:3000')
})
})();
app.get('/', async (req, res) => {
let result = await globalThis.webR.evalR('tools::toTitleCase("hello from r!")');
let output = await result.toJs();
res.send(output.values)
});
Every time I relaunch the app, a package installation is performed:
$ node index.js
webR is ready
Downloading webR package: rlang
Downloading webR package: attempt
http://localhost:3000
$ node index.js
webR is ready
Downloading webR package: rlang
Downloading webR package: attempt
http://localhost:3000
It works but I feel like there should be a better way to do it, because :
- I feel like there is no good reason for downloading the packages every time the app is launched
- If I have a lot of packages, it would take a lot of time every time
- I can't deploy this on a service that has no access to internet
Wishlist :
I would love to have something that allows (in the spirit of node_modules
) to pre-install the packages on my machine and then load them at runtime.
(async () => {
webR = new WebR();
await webR.init();
await webR.loadPackage( path.join(__dirname, '/r-packages/attempt'))
})();
Random thoughts:
I could do it myself by downloading the binaries and toying the WebRFS
interface but :
- I would have to do the dependency tree resolution myself, while webr::install() and install.packages() already have everything set up.
- It might be a bit complex to read the file/folder tree and replicate it on webr filesystem.
Happy to discuss this idea :)
Cheers