---
title: "Node.js Management"
vignette: >
%\VignetteIndexEntry{Node.js Management}
%\VignetteEngine{quarto::html}
%\VignetteEncoding{UTF-8}
knitr:
opts_chunk:
collapse: true
comment: "#>"
---
```{r}
#| include: false
library(shinyelectron)
```
Packaging a Shiny app into an installer needs Node.js. Most R and Python users do not have Node.js on their machines and do not want to install it system-wide just to ship one app. shinyelectron solves the awkward middle by downloading a copy of Node into your user cache: no admin rights, no conflict with anything else, and you can pin or remove it cleanly later.
If you already have a recent Node.js LTS (22 or higher) on your `PATH`, that works too. shinyelectron uses whichever copy it can find.
## Why a local install
A local install lives in your user cache rather than under `/usr/local` or `C:\Program Files`. Four things follow from that.
| Benefit | What it means |
|---------|---------------|
| **No admin rights** | No `sudo` or Administrator prompts during install |
| **Isolation** | Stays out of the way of any system Node.js or other projects |
| **Pinnability** | Lock to a specific version when reproducibility matters |
| **Portability** | Works on locked-down machines where a system install is not allowed |
The minimum supported version is **Node.js 22.0.0** because Electron 41 requires it. shinyelectron's installer always defaults to the latest LTS, which is well above that floor.
## Installing
`install_nodejs()` fetches the latest LTS build from nodejs.org, verifies the checksum, and unpacks it into the cache.
```{r}
#| eval: false
install_nodejs()
```
```
i Detecting latest Node.js LTS version...
v Latest LTS: v22.11.0
-- Installing Node.js v22.11.0 ----------------------------------------------
i Platform: mac
i Architecture: arm64
i Fetching checksums...
i Downloading from https://nodejs.org/dist/v22.11.0/node-v22.11.0-darwin-arm64.tar.gz
v Checksum verified
i Extracting archive...
v Node.js v22.11.0 installed successfully
i Location: /Users/you/Library/Caches/shinyelectron/assets/nodejs/v22.11.0/darwin-arm64
i shinyelectron will automatically use this installation
```
Two arguments worth knowing:
```{r}
#| eval: false
# Pin a specific version for reproducible builds
install_nodejs(version = "22.11.0")
# Force a fresh download when a previous one is corrupt
install_nodejs(force = TRUE)
```
You can install several versions side by side; they sit in separate directories in the cache.
```{r}
#| eval: false
install_nodejs(version = "22.11.0")
install_nodejs(version = "20.18.0")
```
When more than one is present, **the highest semantic version wins** at resolution time. Install order does not matter.
## Which Node.js shinyelectron uses
Whenever shinyelectron needs to run `node` or `npm`, it picks one in this order:
1. **The local install** under the shinyelectron cache. If several local versions are present, the highest wins.
2. **The system Node.js** found on `PATH`.
3. If neither is available, the call fails with a message naming both options.
Node.js resolution: local cache first, then system PATH, then error.
`sitrep_electron_system()` shows what it finds:
```{r}
#| eval: false
sitrep_electron_system()
```
```
-- System Requirements Report ------------------------------------------------
v Platform: mac
v Architecture: arm64
v Local Node.js (shinyelectron): v22.11.0
Other versions: 20.18.0
v Active Node.js: v22.11.0 (local)
v npm: v11.5.0
```
## Auto-install from `_shinyelectron.yml` (planned)
::: {.callout-warning}
## Not yet implemented
`auto_install` is reserved for a future release and has no effect today. A missing Node.js aborts the build with a message directing you to run `install_nodejs()` or install Node.js manually from .
:::
When implemented, setting `auto_install: true` in `_shinyelectron.yml` will let `export()` fetch Node.js automatically when it cannot find one and then continue the build. For now, call `install_nodejs()` before running `export()`.
```{r}
#| eval: false
install_nodejs()
```
## Cache layout
Everything lives under the shinyelectron user cache, organised by version and then platform/architecture. The base directory comes from `rappdirs::user_cache_dir("shinyelectron")`, so the exact path is platform-specific:
| Platform | Typical cache base |
|----------|--------------------|
| macOS | `~/Library/Caches/shinyelectron/assets/` |
| Linux | `~/.cache/shinyelectron/assets/` |
| Windows | `%LOCALAPPDATA%\shinyelectron\Cache\assets\` |
Call `cache_dir()` to get the actual path on your machine. Inside it, the Node.js layout looks like this:
```
{cache_dir()}/nodejs/
|-- v22.11.0/
| `-- darwin-arm64/ # macOS Apple Silicon
| |-- bin/
| | |-- node
| | |-- npm
| | `-- npx
| |-- include/
| `-- lib/
|-- v20.18.0/
| `-- win-x64/ # Windows 64-bit
| |-- node.exe
| |-- npm.cmd
| `-- npx.cmd
`-- ...
```
The platform and architecture come from `Sys.info()` and map to Node.js's own naming:
| Detected (R) | Node.js build |
|--------------|---------------|
| Darwin / arm64 | darwin-arm64 |
| Darwin / x86_64 | darwin-x64 |
| Windows / arm64 | win-arm64 |
| Windows / x86_64 | win-x64 |
| Linux / arm64 | linux-arm64 |
| Linux / x86_64 | linux-x64 |
## Download integrity
Every download is checked against the official SHA256 manifest before it is unpacked:
1. Fetch `SHASUMS256.txt` from nodejs.org.
2. Download the Node.js archive.
3. Compute the SHA256 of the downloaded file.
4. Compare against the expected checksum.
5. Abort on any mismatch; the archive is never extracted.
This catches both ordinary corruption and anything tampered with in transit. If `SHASUMS256.txt` cannot be fetched (a transient network error), shinyelectron warns and continues without verifying rather than failing the install. The portable R and Python runtimes are verified the same way, against their own published checksums.
## Clearing the cache
Remove every Node.js install shinyelectron has downloaded:
```{r}
#| eval: false
cache_clear("nodejs")
```
```
v Cleared Node.js installation cache
```
Remove everything shinyelectron has cached (Node.js, R/Python runtimes, npm modules):
```{r}
#| eval: false
cache_clear("all")
```
Useful when an install is broken, when disk space is tight, or when you want to test a fresh download from scratch.
## Local versus system
| Aspect | Local (shinyelectron) | System |
|--------|------------------------|--------|
| Installs with | `install_nodejs()` | OS package manager or nodejs.org |
| Lives under | `cache_dir()` | `/usr/local`, `C:\Program Files\nodejs` |
| Admin rights | No | Usually yes |
| Updates | `install_nodejs()` | OS package manager |
| Multiple versions | Yes | Usually one |
| Affects other tools | No | Yes |
Prefer the local install for most work. It is isolated, reproducible, and cannot be broken by an OS update. The system install makes sense when your team standardises on a Node version that is already installed everywhere.
## Troubleshooting
### Network error during download
```
x Failed to download Node.js
x URL: https://nodejs.org/dist/v22.11.0/node-v22.11.0-darwin-arm64.tar.gz
x Error: could not resolve host
```
Check your connection. If you are behind a corporate proxy, make sure R sees it (set `HTTPS_PROXY` in your `.Renviron`). If nodejs.org itself is unreachable, retry later.
### Checksum mismatch
```
x Checksum verification failed
x Downloaded file may be corrupted
```
Force a re-download:
```{r}
#| eval: false
install_nodejs(force = TRUE)
```
If the mismatch persists, nodejs.org may be serving a bad mirror. Wait and retry, or pin to a known-good earlier version with `version = "..."`.
### Wrong architecture
Symptom: Node.js runs but Electron fails with an architecture mismatch (for example, `node was compiled for darwin-x64 but the system is darwin-arm64`).
The cached install is the wrong build for your machine. Clear and reinstall:
```{r}
#| eval: false
sitrep_electron_system()
cache_clear("nodejs")
install_nodejs()
```
### Local install skipped
Symptom: shinyelectron keeps reaching for the system Node.js even though `install_nodejs()` reported success.
The local install is probably incomplete. Clear and reinstall, then verify with `sitrep_electron_system()`:
```{r}
#| eval: false
cache_clear("nodejs")
install_nodejs()
sitrep_electron_system()
```
## Next steps
- **[Getting Started](getting-started.html)**: first-time walkthrough.
- **[Configuration](configuration.html)**: full `_shinyelectron.yml` reference.
- **[Troubleshooting](troubleshooting.html)**: diagnose other build issues.