Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
ruby-4.0.0
ruby-4.0.1
30 changes: 21 additions & 9 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@

# For a containerized dev environment, see Dev Containers: https://guides.rubyonrails.org/getting_started_with_devcontainer.html

# Set to "true" to build and ship the SSR runtime; flip and rebuild to toggle.
ARG SSR_ENABLED=false

# Make sure RUBY_VERSION matches the Ruby version in .ruby-version
ARG RUBY_VERSION=4.0.0
ARG RUBY_VERSION=4.0.1
FROM docker.io/library/ruby:$RUBY_VERSION-slim AS base

# Rails app lives here
Expand All @@ -24,7 +27,7 @@ RUN apt-get update -qq && \
ENV RAILS_ENV="production" \
BUNDLE_DEPLOYMENT="1" \
BUNDLE_PATH="/usr/local/bundle" \
BUNDLE_WITHOUT="development:test" \
BUNDLE_WITHOUT="development" \
LD_PRELOAD="/usr/local/lib/libjemalloc.so"

# Throw-away build stage to reduce size of final image
Expand All @@ -35,8 +38,8 @@ RUN apt-get update -qq && \
apt-get install --no-install-recommends -y build-essential git libyaml-dev node-gyp pkg-config python-is-python3 && \
rm -rf /var/lib/apt/lists /var/cache/apt/archives

# Install JavaScript dependencies
ARG NODE_VERSION=22.18.0
# Install Node.js (needed for builds; kept in runtime for SSR)
ARG NODE_VERSION=22.22.2
ENV PATH=/usr/local/node/bin:$PATH
RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \
/tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \
Expand All @@ -53,8 +56,7 @@ RUN bundle install && \

# Install node modules
COPY package.json package-lock.json ./
RUN npm ci && \
rm -rf ~/.npm
RUN npm ci

# Copy application code
COPY . .
Expand All @@ -66,11 +68,21 @@ RUN bundle exec bootsnap precompile -j 1 app/ lib/
# Precompiling assets for production without requiring secret RAILS_MASTER_KEY
RUN SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile

RUN rm -rf node_modules
# Build SSR bundle when SSR_ENABLED=true, then discard node_modules
ARG SSR_ENABLED
RUN if [ "$SSR_ENABLED" = "true" ]; then npx vite build --ssr; fi && \
rm -rf node_modules

# Branch: SSR enabled — ship the JS runtime alongside the app
FROM base AS branch-ssr-true
COPY --from=build /usr/local/node /usr/local/node
ENV PATH=/usr/local/node/bin:$PATH

# Branch: SSR disabled — base only, no JS runtime
FROM base AS branch-ssr-false

# Final stage for app image
FROM base
# Final stage for app image: picks the right branch by SSR_ENABLED
FROM branch-ssr-${SSR_ENABLED} AS final

# Run and own only the runtime files as a non-root user for security
RUN groupadd --system --gid 1000 rails && \
Expand Down
90 changes: 0 additions & 90 deletions Dockerfile-ssr

This file was deleted.

2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ gem "thruster", require: false
gem "vite_rails", "~> 3.0"

# The Rails adapter for Inertia.js [https://inertia-rails.dev]
gem "inertia_rails", "~> 3.19"
gem "inertia_rails", "~> 3.21"

# An authentication system generator for Rails applications
# we leave gem here to watch for security updates
Expand Down
36 changes: 18 additions & 18 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
action_text-trix (2.1.18)
action_text-trix (2.1.19)
railties
actioncable (8.1.3)
actionpack (= 8.1.3)
Expand Down Expand Up @@ -85,7 +85,7 @@ GEM
benchmark (0.5.0)
bigdecimal (4.1.2)
bindex (0.8.1)
bootsnap (1.24.1)
bootsnap (1.24.4)
msgpack (~> 1.2)
brakeman (8.0.4)
racc
Expand Down Expand Up @@ -123,7 +123,7 @@ GEM
erubi (1.13.1)
et-orbi (1.4.0)
tzinfo
factory_bot (6.5.6)
factory_bot (6.6.0)
activesupport (>= 6.1.0)
factory_bot_rails (6.5.1)
factory_bot (~> 6.5)
Expand All @@ -146,7 +146,7 @@ GEM
jbuilder (2.14.1)
actionview (>= 7.0.0)
activesupport (>= 7.0.0)
json (2.19.4)
json (2.19.5)
kamal (2.11.0)
activesupport (>= 7.0)
base64 (~> 0.2)
Expand Down Expand Up @@ -235,7 +235,7 @@ GEM
raabro (1.4.0)
racc (1.8.1)
rack (3.2.6)
rack-proxy (0.7.7)
rack-proxy (0.8.2)
rack
rack-session (2.1.2)
base64 (>= 0.1.0)
Expand Down Expand Up @@ -301,7 +301,7 @@ GEM
rspec-mocks (>= 3.13.0, < 5.0.0)
rspec-support (>= 3.13.0, < 5.0.0)
rspec-support (3.13.7)
rubocop (1.86.1)
rubocop (1.86.2)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
Expand All @@ -319,7 +319,7 @@ GEM
lint_roller (~> 1.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.47.1, < 2.0)
rubocop-rails (2.34.3)
rubocop-rails (2.35.0)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
Expand All @@ -330,9 +330,9 @@ GEM
rubocop-performance (>= 1.24)
rubocop-rails (>= 2.30)
ruby-progressbar (1.13.0)
rubyzip (3.2.2)
rubyzip (3.3.0)
securerandom (0.4.1)
selenium-webdriver (4.43.0)
selenium-webdriver (4.44.0)
base64 (~> 0.2)
logger (~> 1.4)
rexml (~> 3.2, >= 3.2.5)
Expand All @@ -354,13 +354,13 @@ GEM
fugit (~> 1.11)
railties (>= 7.1)
thor (>= 1.3.1)
sqlite3 (2.9.3-aarch64-linux-gnu)
sqlite3 (2.9.3-aarch64-linux-musl)
sqlite3 (2.9.3-arm-linux-gnu)
sqlite3 (2.9.3-arm-linux-musl)
sqlite3 (2.9.3-arm64-darwin)
sqlite3 (2.9.3-x86_64-linux-gnu)
sqlite3 (2.9.3-x86_64-linux-musl)
sqlite3 (2.9.4-aarch64-linux-gnu)
sqlite3 (2.9.4-aarch64-linux-musl)
sqlite3 (2.9.4-arm-linux-gnu)
sqlite3 (2.9.4-arm-linux-musl)
sqlite3 (2.9.4-arm64-darwin)
sqlite3 (2.9.4-x86_64-linux-gnu)
sqlite3 (2.9.4-x86_64-linux-musl)
sshkit (1.25.0)
base64
logger
Expand All @@ -386,7 +386,7 @@ GEM
unicode-emoji (4.2.0)
uri (1.1.1)
useragent (0.16.11)
vite_rails (3.10.0)
vite_rails (3.11.0)
railties (>= 5.1, < 9)
vite_ruby (~> 3.0, >= 3.2.2)
vite_ruby (3.10.2)
Expand Down Expand Up @@ -429,7 +429,7 @@ DEPENDENCIES
capybara-lockstep
debug
factory_bot_rails
inertia_rails (~> 3.19)
inertia_rails (~> 3.21)
jbuilder
kamal
letter_opener
Expand Down
62 changes: 28 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,43 +29,37 @@ See also:

## Enabling SSR

This starter kit comes with optional SSR support. To enable it, follow these steps:

1. Open `app/frontend/entrypoints/inertia.ts` and uncomment part of the `setup` function:
```ts
// Uncomment the following to enable SSR hydration:
// if (el.hasChildNodes()) {
// hydrateRoot(el, createElement(App, props))
// return
// }
```
2. Open `config/deploy.yml` and uncomment several lines:
This starter kit ships SSR-ready but turned off. The Puma plugin
([`plugin :inertia_ssr`](config/puma.rb)) manages the Node.js renderer
in-process — no separate accessory required.

To turn SSR on, flip two switches:

1. Set `config.ssr_enabled = true` in [`config/initializers/inertia_rails.rb`](config/initializers/inertia_rails.rb).
2. Build the image with `SSR_ENABLED=true` so the SSR bundle ships
alongside the app. Two ways:

**With Kamal** — add to [`config/deploy.yml`](config/deploy.yml):

```yml
servers:
# Uncomment to enable SSR:
# vite_ssr:
# hosts:
# - 192.168.0.1
# cmd: bundle exec vite ssr
# options:
# network-alias: vite_ssr

# ...

env:
clear:
# Uncomment to enable SSR:
# INERTIA_SSR_ENABLED: true
# INERTIA_SSR_URL: "http://vite_ssr:13714"

# ...

builder:
# Uncomment to enable SSR:
# dockerfile: Dockerfile-ssr
args:
SSR_ENABLED: true
```

That's it! Now you can deploy your app with SSR support.

**By hand** — pass the build arg directly:

```bash
docker build --build-arg SSR_ENABLED=true -t react_starter_kit .
```

That's it. Puma boots the SSR process automatically when
`ssr_enabled` is true, and Inertia falls back to client-side
rendering if it ever fails (see `config.on_ssr_error`).

In development, flipping `ssr_enabled` is enough — Vite serves SSR
via its own dev endpoint with HMR. The Docker build arg only matters
for production images.

## License

Expand Down
Loading