Skip to content

Commit afec3b5

Browse files
skryukovbknoles
authored andcommitted
Add v2 docs
1 parent 234aaab commit afec3b5

14 files changed

+1363
-27
lines changed

docs/.vitepress/config.mts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ export default defineConfig({
7171
items: [
7272
{ text: 'Introduction', link: '/guide' },
7373
{ text: 'Demo app', link: '/guide/demo-application' },
74+
{ text: 'Upgrade guide', link: '/guide/upgrade-guide' },
7475
],
7576
},
7677
{
@@ -101,28 +102,44 @@ export default defineConfig({
101102
{ text: 'Forms', link: '/guide/forms' },
102103
{ text: 'File uploads', link: '/guide/file-uploads' },
103104
{ text: 'Validation', link: '/guide/validation' },
104-
{ text: 'Shared data', link: '/guide/shared-data' },
105105
],
106106
},
107107
{
108-
text: 'Advanced',
108+
text: 'Data & Props',
109109
items: [
110-
{ text: 'Events', link: '/guide/events' },
111-
{ text: 'Testing', link: '/guide/testing' },
110+
{ text: 'Shared data', link: '/guide/shared-data' },
112111
{ text: 'Partial reloads', link: '/guide/partial-reloads' },
113-
{ text: 'Scroll management', link: '/guide/scroll-management' },
112+
{ text: 'Deferred props', link: '/guide/deferred-props' },
113+
{ text: 'Polling', link: '/guide/polling' },
114+
{ text: 'Prefetching', link: '/guide/prefetching' },
115+
{ text: 'Load when visible', link: '/guide/load-when-visible' },
116+
{ text: 'Merging props', link: '/guide/merging-props' },
117+
{ text: 'Remembering state', link: '/guide/remembering-state' },
118+
],
119+
},
120+
{
121+
text: 'Security',
122+
items: [
114123
{ text: 'Authentication', link: '/guide/authentication' },
115124
{ text: 'Authorization', link: '/guide/authorization' },
116125
{ text: 'CSRF protection', link: '/guide/csrf-protection' },
117-
{ text: 'Error handling', link: '/guide/error-handling' },
126+
{ text: 'History encryption', link: '/guide/history-encryption' },
127+
],
128+
},
129+
{
130+
text: 'Advanced',
131+
items: [
118132
{ text: 'Asset versioning', link: '/guide/asset-versioning' },
119-
{ text: 'Progress indicators', link: '/guide/progress-indicators' },
120-
{ text: 'Remembering state', link: '/guide/remembering-state' },
121133
{ text: 'Code splitting', link: '/guide/code-splitting' },
134+
{ text: 'Error handling', link: '/guide/error-handling' },
135+
{ text: 'Events', link: '/guide/events' },
136+
{ text: 'Progress indicators', link: '/guide/progress-indicators' },
137+
{ text: 'Scroll management', link: '/guide/scroll-management' },
122138
{
123139
text: 'Server-side rendering',
124140
link: '/guide/server-side-rendering',
125141
},
142+
{ text: 'Testing', link: '/guide/testing' },
126143
],
127144
},
128145
],

docs/guide/deferred-props.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Deferred props
2+
3+
Inertia's deferred props feature allows you to defer the loading of certain page data until after the initial page render. This can be useful for improving the perceived performance of your app by allowing the initial page render to happen as quickly as possible.
4+
5+
## Server side
6+
7+
To defer a prop, you can use the defer method when returning your response. This method receives a callback that returns the prop data. The callback will be executed in a separate request after the initial page render.
8+
9+
```ruby
10+
class UsersController < ApplicationController
11+
def index
12+
render inertia: 'Users/Index', props: {
13+
users: -> { User.all },
14+
roles: -> { Role.all },
15+
permissions: InertiaRails.defer { Permission.all },
16+
}
17+
end
18+
end
19+
```
20+
21+
### Grouping requests
22+
23+
By default, all deferred props get fetched in one request after the initial page is rendered, but you can choose to fetch data in parallel by grouping props together.
24+
25+
```ruby
26+
class UsersController < ApplicationController
27+
def index
28+
render inertia: 'Users/Index', props: {
29+
users: -> { User.all },
30+
roles: -> { Role.all },
31+
permissions: InertiaRails.defer { Permission.all },
32+
teams: InertiaRails.defer(group: 'attributes') { Team.all },
33+
projects: InertiaRails.defer(group: 'attributes') { Project.all },
34+
tasks: InertiaRails.defer(group: 'attributes') { Task.all },
35+
}
36+
end
37+
end
38+
```
39+
40+
In the example above, the `teams`, `projects`, and `tasks` props will be fetched in one request, while the `permissions` prop will be fetched in a separate request in parallel. Group names are arbitrary strings and can be anything you choose.
41+
42+
## Client side
43+
44+
On the client side, Inertia provides the `Deferred` component to help you manage deferred props. This component will automatically wait for the specified deferred props to be available before rendering its children.
45+
46+
:::tabs key:frameworks
47+
== Vue
48+
49+
```vue
50+
<script setup>
51+
import { Deferred } from '@inertiajs/vue3'
52+
</script>
53+
54+
<template>
55+
<Deferred data="permissions">
56+
<template #fallback>
57+
<div>Loading...</div>
58+
</template>
59+
<div v-for="permission in permissions">
60+
<!-- ... -->
61+
</div>
62+
</Deferred>
63+
</template>
64+
```
65+
66+
== React
67+
68+
```jsx
69+
import { Deferred } from '@inertiajs/react'
70+
71+
export default () => (
72+
<Deferred data="permissions" fallback={<div>Loading...</div>}>
73+
<PermissionsChildComponent />
74+
</Deferred>
75+
)
76+
```
77+
78+
== Svelte 4
79+
80+
```svelte
81+
<script>
82+
import { Deferred } from '@inertiajs/svelte'
83+
export let permissions
84+
</script>
85+
86+
<Deferred data="permissions">
87+
<svelte:fragment slot="fallback">
88+
<div>Loading...</div>
89+
</svelte:fragment>
90+
91+
{#each permissions as permission}
92+
<!-- ... -->
93+
{/each}
94+
</Deferred>
95+
```
96+
97+
== Svelte 5
98+
99+
```svelte
100+
<script>
101+
import { Deferred } from '@inertiajs/svelte'
102+
let { permissions } = $props()
103+
</script>
104+
105+
<Deferred data="permissions">
106+
{#snippet fallback()}
107+
<div>Loading...</div>
108+
{/snippet}
109+
110+
{#each permissions as permission}
111+
<!-- ... -->
112+
{/each}
113+
</Deferred>
114+
```
115+
116+
:::
117+
118+
If you need to wait for multiple deferred props to become available, you can specify an array to the `data` prop.
119+
120+
:::tabs key:frameworks
121+
== Vue
122+
123+
```vue
124+
<script setup>
125+
import { Deferred } from '@inertiajs/vue3'
126+
</script>
127+
128+
<template>
129+
<Deferred :data="['teams', 'users']">
130+
<template #fallback>
131+
<div>Loading...</div>
132+
</template>
133+
<!-- Props are now loaded -->
134+
</Deferred>
135+
</template>
136+
```
137+
138+
== React
139+
140+
```jsx
141+
import { Deferred } from '@inertiajs/react'
142+
143+
export default () => (
144+
<Deferred data={['teams', 'users']} fallback={<div>Loading...</div>}>
145+
<ChildComponent />
146+
</Deferred>
147+
)
148+
```
149+
150+
== Svelte 4
151+
152+
```svelte
153+
<script>
154+
import { Deferred } from '@inertiajs/svelte'
155+
export let teams
156+
export let users
157+
</script>
158+
159+
<Deferred data={['teams', 'users']}>
160+
<svelte:fragment slot="fallback">
161+
<div>Loading...</div>
162+
</svelte:fragment>
163+
164+
<!-- Props are now loaded -->
165+
</Deferred>
166+
```
167+
168+
== Svelte 5
169+
170+
```svelte
171+
<script>
172+
import { Deferred } from '@inertiajs/svelte'
173+
let { teams, users } = $props()
174+
</script>
175+
176+
<Deferred data={['teams', 'users']}>
177+
{#snippet fallback()}
178+
<div>Loading...</div>
179+
{/snippet}
180+
181+
<!-- Props are now loaded -->
182+
</Deferred>
183+
```
184+
185+
:::

docs/guide/history-encryption.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# History encryption
2+
3+
Imagine a scenario where your user is authenticated, browses privileged information on your site, then logs out. If they press the back button, they can still see the privileged information that is stored in the window's history state. This is a security risk. To prevent this, Inertia.js provides a history encryption feature.
4+
5+
## How it works
6+
7+
When you instruct Inertia to encrypt your app's history, it uses the browser's built-in [`crypto` api](https://developer.mozilla.org/en-US/docs/Web/API/Crypto) to encrypt the current page's data before pushing it to the history state. We store the corresponding key in the browser's session storage. When the user navigates back to a page, we decrypt the data using the key stored in the session storage.
8+
9+
Once you instruct Inertia to clear your history state, we simply clear the existing key from session storage roll a new one. If we attempt to decrypt the history state with the new key, it will fail an Inertia will make a fresh request back to your server for the page data.
10+
11+
> [!NOTE]
12+
> History encryption relies on `window.crypto.subtle` which is only available in secure environments (sites with SSL enabled).
13+
14+
## Opting in
15+
16+
History encryption is an opt-in feature. There are several methods for enabling it:
17+
18+
### Global encryption
19+
20+
If you'd like to enable history encryption globally, set the `encrypt_history` config value to `true`.
21+
22+
You are able to opt out of encryption on specific pages by passing `false` to the `encrypt_history` option:
23+
24+
```ruby
25+
render inertia: 'Homepage', props: {}, encrypt_history: false
26+
```
27+
28+
### Per-request encryption
29+
30+
To encrypt the history of an individual request, simply pass `true` to the `encrypt_history` option:
31+
32+
```ruby
33+
render inertia: 'Dashboard', props: {}, encrypt_history: true
34+
```
35+
36+
### Controller-level encryption
37+
38+
You can also enable history encryption for all actions in a controller by setting the `encrypt_history` config value in the controller:
39+
40+
```ruby
41+
class DashboardController < ApplicationController
42+
inertia_config(encrypt_history: true)
43+
44+
# ...
45+
end
46+
```
47+
48+
## Clearing history
49+
50+
To clear the history state, you can pass the `clear_history` option to the `render` method:
51+
52+
```ruby
53+
render inertia: 'Dashboard', props: {}, clear_history: true
54+
```
55+
56+
Once the response has rendered on the client, the encryption key will be rotated, rendering the previous history state unreadable.
57+
58+
You can also clear history on the client site by calling `router.clearHistory()`.

docs/guide/links.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,3 +522,7 @@ export default () => {
522522
You can perform exact match comparisons (`===`), `startsWith()` comparisons (useful for matching a subset of pages), or even more complex comparisons using regular expressions.
523523

524524
Using this approach, you're not limited to just setting class names. You can use this technique to conditionally render any markup on active state, such as different link text or even an SVG icon that represents the link is active.
525+
526+
## Data loading attribute
527+
528+
While a link is making an active request, a `data-loading` attribute is added to the link element. This allows you to style the link while it's in a loading state. The attribute is removed once the request is complete.

0 commit comments

Comments
 (0)