Skip to content

Commit e70f54a

Browse files
authored
Merge pull request #299 from inertiajs/render-data-in-script-tag
Ability to use `<script>` element for initial page data
2 parents 49947f3 + 28f1aa9 commit e70f54a

37 files changed

+1464
-215
lines changed

.github/workflows/docs.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ jobs:
2323

2424
steps:
2525
- name: Checkout repository
26-
uses: actions/checkout@v4
26+
uses: actions/checkout@v6
2727

2828
- name: Setup Node.js
29-
uses: actions/setup-node@v4
29+
uses: actions/setup-node@v6
3030
with:
3131
node-version: '22'
3232
cache: 'npm'

.github/workflows/generators.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
name: ${{ matrix.framework }} (TS:${{ matrix.typescript }}, TW:${{ matrix.tailwind }}, Inertia:${{ matrix.inertia_version }})
3131

3232
steps:
33-
- uses: actions/checkout@v4
33+
- uses: actions/checkout@v6
3434

3535
- name: Set up Ruby
3636
uses: ruby/setup-ruby@v1
@@ -42,7 +42,7 @@ jobs:
4242
run: bundle exec rspec --tag type:generator
4343

4444
- name: Set up Node
45-
uses: actions/setup-node@v4
45+
uses: actions/setup-node@v6
4646
with:
4747
node-version: ${{ matrix.node }}
4848

@@ -69,7 +69,7 @@ jobs:
6969
7070
- name: Upload test artifacts
7171
if: failure()
72-
uses: actions/upload-artifact@v4
72+
uses: actions/upload-artifact@v5
7373
with:
7474
name: test-output-${{ matrix.framework }}-ts${{ matrix.typescript }}-tw${{ matrix.tailwind }}-v${{ matrix.inertia_version }}
7575
path: |

.github/workflows/push.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ jobs:
1919
runs-on: ubuntu-latest
2020
name: Linter
2121
steps:
22-
- uses: actions/checkout@v4
22+
- uses: actions/checkout@v6
2323
- name: Set up Ruby
2424
uses: ruby/setup-ruby@v1
2525
with:
26-
ruby-version: "3.3"
26+
ruby-version: "3.4"
2727
bundler: latest
2828
bundler-cache: true
2929
- name: Run RuboCop
@@ -53,21 +53,21 @@ jobs:
5353
name: Test against Ruby ${{ matrix.ruby }} / Rails ${{ matrix.rails }}
5454

5555
steps:
56-
- uses: actions/checkout@v4
56+
- uses: actions/checkout@v6
5757

5858
- name: Setup System
5959
run: sudo apt-get install libsqlite3-dev
6060

6161
- name: Set up Node.js
62-
uses: actions/setup-node@v4
62+
uses: actions/setup-node@v6
6363
with:
6464
node-version: 22.x
6565

6666
- name: Set up Ruby
6767
uses: ruby/setup-ruby@v1
6868
with:
6969
ruby-version: ${{ matrix.ruby }}
70-
rubygems: latest
70+
rubygems: 'latest'
7171
bundler-cache: true
7272
env:
7373
RAILS_VERSION: ${{ matrix.rails }}

Gemfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ gemspec
88
version = ENV.fetch('RAILS_VERSION', '8.1')
99
gem 'rails', "~> #{version}.0"
1010

11-
gem 'bundler', '~> 2.0'
1211
gem 'debug'
1312
gem 'generator_spec', '~> 0.10'
1413
gem 'rails-controller-testing'

app/views/inertia.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<div id="app" data-page="<%= page.to_json %>"></div>
1+
<%= inertia_root(page: page) %>

docs/.vitepress/config.mts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ export default defineConfig({
136136
{ text: 'Prefetching', link: '/guide/prefetching' },
137137
{ text: 'Load when visible', link: '/guide/load-when-visible' },
138138
{ text: 'Merging props', link: '/guide/merging-props' },
139+
{ text: 'Once props', link: '/guide/once-props' },
139140
{ text: 'Infinite scroll', link: '/guide/infinite-scroll' },
140141
{ text: 'Remembering state', link: '/guide/remembering-state' },
141142
],

docs/cookbook/handling-validation-error-types.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ import type { InertiaFormProps as OriginalProps } from '@inertiajs/vue3'
2626
type FormDataType = Record<string, FormDataConvertible>
2727

2828
declare module '@inertiajs/vue3' {
29-
interface InertiaFormProps<TForm extends FormDataType>
30-
extends Omit<OriginalProps<TForm>, 'errors' | 'setError'> {
29+
interface InertiaFormProps<TForm extends FormDataType> extends Omit<
30+
OriginalProps<TForm>,
31+
'errors' | 'setError'
32+
> {
3133
errors: Partial<Record<FormDataKeys<TForm>, string[]>>
3234

3335
setError(field: FormDataKeys<TForm>, value: string[]): this
@@ -60,8 +62,10 @@ import type { InertiaFormProps as OriginalProps } from '@inertiajs/react'
6062
type FormDataType = Record<string, FormDataConvertible>
6163

6264
declare module '@inertiajs/react' {
63-
interface InertiaFormProps<TForm extends FormDataType>
64-
extends Omit<OriginalProps<TForm>, 'errors' | 'setError'> {
65+
interface InertiaFormProps<TForm extends FormDataType> extends Omit<
66+
OriginalProps<TForm>,
67+
'errors' | 'setError'
68+
> {
6569
errors: Partial<Record<FormDataKeys<TForm>, string[]>>
6670

6771
setError(field: FormDataKeys<TForm>, value: string[]): void
@@ -92,8 +96,10 @@ import type { Writable } from 'svelte/store'
9296
type FormDataType = Record<string, FormDataConvertible>
9397

9498
declare module '@inertiajs/svelte' {
95-
interface InertiaFormProps<TForm extends FormDataType>
96-
extends Omit<OriginalProps<TForm>, 'errors' | 'setError'> {
99+
interface InertiaFormProps<TForm extends FormDataType> extends Omit<
100+
OriginalProps<TForm>,
101+
'errors' | 'setError'
102+
> {
97103
errors: Partial<Record<FormDataKeys<TForm>, string[]>>
98104

99105
setError(field: FormDataKeys<TForm>, value: string[]): this

docs/guide/client-side-setup.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,3 +292,26 @@ createInertiaApp({
292292
// ...
293293
})
294294
```
295+
296+
> [!NOTE]
297+
> Make sure the [`root_dom_id`](/guide/configuration#root_dom_id) configuration option matches the `id` property in your client-side setup.
298+
299+
## Script Element for Page Data
300+
301+
By default, Inertia stores the initial page data in a `data-page` attribute on the root element. You may configure Inertia to use a `<script type="application/json">` element instead, which is slightly faster and easier to inspect in your browser's dev tools.
302+
303+
```js
304+
createInertiaApp({
305+
// ...
306+
defaults: {
307+
future: {
308+
useScriptElementForInitialPage: true,
309+
},
310+
},
311+
})
312+
```
313+
314+
You should also set the [`use_script_element_for_initial_page`](/guide/configuration#use_script_element_for_initial_page) config option to `true`.
315+
316+
> [!NOTE]
317+
> Be sure to also update your [SSR entry point](/guide/server-side-rendering#add-server-entry-point) if you're using server-side rendering.

docs/guide/configuration.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,59 @@ The default value will be changed to `true` in the next major version.
151151
Specifies the base controller class for the internal `StaticController` used to render [Shorthand routes](/guide/routing#shorthand-routes).
152152

153153
By default, Inertia Rails creates a `StaticController` that inherits from `ApplicationController`. You can use this option to specify a different base controller (for example, to include custom authentication, layout, or before actions).
154+
155+
### `root_dom_id`
156+
157+
**Default**: `'app'`
158+
**ENV**: `INERTIA_ROOT_DOM_ID`
159+
160+
@available_since rails=master
161+
162+
Specifies the DOM element ID used for the root Inertia.js element.
163+
164+
```ruby
165+
InertiaRails.configure do |config|
166+
config.root_dom_id = 'inertia-app'
167+
end
168+
```
169+
170+
> [!NOTE]
171+
> Make sure your client-side Inertia setup uses the same ID when calling `createInertiaApp`.
172+
173+
### `use_script_element_for_initial_page`
174+
175+
**Default**: `false`
176+
**ENV**: `INERTIA_USE_SCRIPT_ELEMENT_FOR_INITIAL_PAGE`
177+
178+
@available_since rails=master core=2.2.20
179+
180+
When enabled the initial page data is rendered in a `<script type="application/json">` element instead of the `data-page` attribute on the root `<div>`.
181+
This provides two main benefits:
182+
183+
1. **Smaller page size**: JSON data doesn't require HTML entity encoding, reducing the overall HTML payload size.
184+
2. **Faster parsing**: The browser can parse raw JSON directly from the script element, which is more efficient than parsing HTML-encoded JSON from an attribute.
185+
186+
```ruby
187+
InertiaRails.configure do |config|
188+
config.use_script_element_for_initial_page = true
189+
end
190+
```
191+
192+
When disabled (default), the HTML output looks like:
193+
194+
```html
195+
<div id="app" data-page='{"component":"Users/Index",...}'></div>
196+
```
197+
198+
When enabled, the HTML output looks like:
199+
200+
```html
201+
<script data-page="app" type="application/json">
202+
{"component":"Users/Index",...}
203+
</script>
204+
<div id="app"></div>
205+
```
206+
207+
> [!NOTE]
208+
> When using this option make sure your client-side Inertia setup is configured to read the page data from the `<script>` element.
209+
> See the [client side setup](/guide/client-side-setup#script-element-for-page-data) for more details.

docs/guide/deferred-props.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ export default () => (
121121

122122
:::
123123

124+
## Multiple Deferred Props
125+
124126
If you need to wait for multiple deferred props to become available, you can specify an array to the `data` prop.
125127

126128
:::tabs key:frameworks
@@ -189,3 +191,21 @@ export default () => (
189191
```
190192

191193
:::
194+
195+
## Combining with Once Props
196+
197+
@available_since rails=master core=2.2.20
198+
199+
You may pass the `once: true` argument to a deferred prop to ensure the data is resolved only once and remembered by the client across subsequent navigations.
200+
201+
```ruby
202+
class DashboardController < ApplicationController
203+
def index
204+
render inertia: {
205+
stats: InertiaRails.defer(once: true) { Stats.generate },
206+
}
207+
end
208+
end
209+
```
210+
211+
For more information on once props, see the [once props](/guide/once-props) documentation.

0 commit comments

Comments
 (0)