Svelte SSR Server

The SSR server acts as a child process of Puma.

It starts and stops alongside Puma.

The only thing you need to consider is having a current Node.js installation on your development and remote machines.

CAVEAT:

The SsrClient, which is part of the Ruby gem, is initialized when Rails boots. To distinguish between a rake task and an actual Rails server launch, the BootContext module was built. However, this detection is not fully reliable.

It is written pessimistically: the SSR client only starts when we are sure Rails is booted for serving HTTP; otherwise it prefers not to start. For ~95% of app setups and deployment pipelines, this should work out of the box. If the SsrClient is not initialized at boot, it will be initialized lazily on the first request for a Svelte component that is rendered (not found in the cache).

Requirements

A current Node.js installation.

The path to Node can be set via the environment variable SVELTE_ON_RAILS_NODE_BIN.

If it is not set, the gem checks whether nvm is installed, by looking for the NVM_DIR environment variable or for ~/.nvm and it checks for a .nvmrc within Rails.root.

The @csedl/svelte-on-rails package must be installed, as it provides the bin/svelte-ssr-server and bin/svelte-ssr-cluster executables.

Both are validated and started when Rails boots.

Setting ssr to false in the configs (see next section) disables all of this.

Configuration

From within the config file svelte_on_rails.yml:

ssr: :auto
# options: true, false, :auto
# :auto: render server side if request is initial request (works only with turbo, because it checks for the X-Turbo-Request-ID header)
# when not server-side rendered the components must be built as custom elements, see node-package @csedl/svelte-on-rails
# false disables SSR for all and overrides the ssr argument of the view helper.
# tip: set it to false for test

ssr_server: true
# Node server on the backend for speedup server side rendering
# default: true for all environments, except test
# docs: https://svelte-on-rails.dev/configuration/svelte_ssr_server.html

ssr_server_workers: 1
# number of Node cluster workers; 1 = no cluster

ssr_fallback_renderer: false
# Node script that does not need a running node server
# default: false

ssr_error_tag: true
# Render the error tag when server side rendering fails
# default: true
# tip: set it to false for production

How it works

  • On boot, the gem starts the Node server or cluster.
    • A socket file is created at <Rails.root>/tmp/sockets/svelte-ssr-<App-Name>-<Rails.env>-<Process.ppid>.sock.
    • If this path is too long, it falls back to /tmp.
  • On restart / deployment
    • The SSR Server is restarted on every deploy. If the restart fails, the deploy halts with an error.
    • Old instances and stale socket files — identified by the prefix svelte-ssr-<App-Name>-<Rails.env> combined with a different ppid — are cleaned up.
  • Rake tasks
    • Rake tasks such as db:migrate also load the Rails environment, which would normally trigger a boot. To avoid starting an SSR Server for them, railtie.rb inspects top_level_tasks and skips SSR initialization in that case.
  • If the Node server crashes (which should never happen), it is restarted automatically.

Troubleshooting

Running rails svelte_on_rails:check prints a status page with all parameters and, if available, the status of the currently running Node instance.

It also prints the trace of how it tried to find — or successfully found — Node.

The output includes a curl command that lets you inspect the status page of the running instance directly:

curl --unix-socket <socket-file> http://localhost

Running node process you can find by

ps aux | grep svelte

Logfile

The SSR server writes an additional log file to <Rails.root>/log/svelte-ssr-server.log.

This log file is deleted every time Rails boots up and mainly contains logs for booting or restarting the SSR server.

This is because boot processes are not always written to the Rails log.