Skip to content

Commit 76bf077

Browse files
committed
dev ssr
1 parent 3701734 commit 76bf077

File tree

10 files changed

+61
-166
lines changed

10 files changed

+61
-166
lines changed

packages/core/build.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const builds = [
1717
{ entryPoints: ['src/index.ts'], format: 'cjs', outfile: 'dist/index.js', platform: 'browser' },
1818
{ entryPoints: ['src/server.ts'], format: 'esm', outfile: 'dist/server.esm.js', platform: 'node' },
1919
{ entryPoints: ['src/server.ts'], format: 'cjs', outfile: 'dist/server.js', platform: 'node' },
20+
{ entryPoints: ['src/vite.ts'], format: 'esm', outfile: 'dist/vite.js', platform: 'node' },
2021
]
2122

2223
builds.forEach((build) => {

packages/core/package.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
"types": "./types/server.d.ts",
3535
"import": "./dist/server.esm.js",
3636
"require": "./dist/server.js"
37+
},
38+
"./vite": {
39+
"types": "./types/vite.d.ts",
40+
"default": "./dist/vite.js"
3741
}
3842
},
3943
"typesVersions": {

packages/core/src/server.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,11 @@
11
import { createServer, IncomingMessage } from 'http'
22
import * as process from 'process'
3-
import { InertiaAppResponse, Page } from './types'
3+
import { readableToString } from './serverUtils'
4+
import type { InertiaAppResponse, Page } from './types'
45

5-
type AppCallback = (page: Page) => InertiaAppResponse
6-
type RouteHandler = (request: IncomingMessage) => Promise<unknown>
6+
export type AppCallback = (page: Page) => InertiaAppResponse
77

8-
const readableToString: (readable: IncomingMessage) => Promise<string> = (readable) =>
9-
new Promise((resolve, reject) => {
10-
let data = ''
11-
readable.on('data', (chunk) => (data += chunk))
12-
readable.on('end', () => resolve(data))
13-
readable.on('error', (err) => reject(err))
14-
})
8+
type RouteHandler = (request: IncomingMessage) => Promise<unknown>
159

1610
export default (render: AppCallback, port?: number): void => {
1711
const _port = port || 13714

packages/core/src/serverUtils.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type { IncomingMessage } from 'http'
2+
3+
export const readableToString: (readable: IncomingMessage) => Promise<string> = (readable) =>
4+
new Promise((resolve, reject) => {
5+
let data = ''
6+
readable.on('data', (chunk) => (data += chunk))
7+
readable.on('end', () => resolve(data))
8+
readable.on('error', (err) => reject(err))
9+
})

packages/core/src/vite.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { Plugin } from 'vite'
2+
import { readableToString } from './serverUtils'
3+
4+
interface PluginConfig {
5+
renderer: string
6+
}
7+
8+
export default function inertia(config: PluginConfig): Plugin {
9+
// todo: validate config
10+
11+
return {
12+
name: '@inertiajs/svelte/ssr',
13+
async configureServer(server) {
14+
return () =>
15+
server.middlewares.use(async (req, res, next) => {
16+
if (req.url !== '/render') {
17+
next()
18+
}
19+
20+
// todo: check if render is a function
21+
const { render } = await server.ssrLoadModule(config.renderer)
22+
const response = await render(JSON.parse(await readableToString(req)))
23+
res.writeHead(200, { 'Content-Type': 'application/json' })
24+
res.end(JSON.stringify(response))
25+
})
26+
},
27+
}
28+
}

packages/svelte/src/server.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
export * from '@inertiajs/core/server'
12
export { default as default } from '@inertiajs/core/server'

playgrounds/svelte5/app/Providers/AppServiceProvider.php

Lines changed: 1 addition & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
namespace App\Providers;
44

5-
use Illuminate\Foundation\Vite;
6-
use Illuminate\Support\HtmlString;
7-
use Illuminate\Support\Js;
85
use Illuminate\Support\ServiceProvider;
96

107
class AppServiceProvider extends ServiceProvider
@@ -16,157 +13,7 @@ class AppServiceProvider extends ServiceProvider
1613
*/
1714
public function register()
1815
{
19-
$this->app->singleton(Vite::class, fn () => new class extends Vite
20-
{
21-
/**
22-
* The prefetching strategy to use.
23-
*
24-
* @var 'waterfall'|'aggressive'
25-
*/
26-
protected $prefetchStrategy = 'waterfall';
27-
28-
/**
29-
* When using the "waterfall" strategy, the count of assets to load at one time.
30-
*
31-
* @param int
32-
*/
33-
protected $prefetchChunks = 3;
34-
35-
/**
36-
* Set the prefetching strategy.
37-
*
38-
* @param 'waterfall'|'aggressive' $strategy
39-
* @param ...mixed $config
40-
*/
41-
public function usePrefetchStrategy(string $strategy, mixed ...$config): static
42-
{
43-
$this->prefetchStrategy = $strategy;
44-
45-
if ($strategy === 'waterfall') {
46-
$this->prefetchChunks = $config[0] ?? 3;
47-
}
48-
49-
return $this;
50-
}
51-
52-
/**
53-
* Generate Vite tags for an entrypoint.
54-
*
55-
* @param string|string[] $entrypoints
56-
* @param string|null $buildDirectory
57-
* @return \Illuminate\Support\HtmlString
58-
*/
59-
public function __invoke($entrypoints, $buildDirectory = null)
60-
{
61-
$manifest = $this->manifest($buildDirectory ??= $this->buildDirectory);
62-
$base = parent::__invoke($entrypoints, $buildDirectory);
63-
64-
if ($this->isRunningHot()) {
65-
return $base;
66-
}
67-
68-
return collect($entrypoints)
69-
->flatMap(fn ($entrypoint) => collect($manifest[$entrypoint]['dynamicImports'] ?? [])
70-
->map(fn ($import) => $manifest[$import])
71-
->filter(fn ($chunk) => str_ends_with($chunk['file'], '.js') || str_ends_with($chunk['file'], '.css'))
72-
->flatMap($resolveImportChunks = function ($chunk) use (&$resolveImportChunks, $manifest) {
73-
return collect([...$chunk['imports'] ?? [], ...$chunk['dynamicImports'] ?? []])
74-
->reduce(
75-
fn ($chunks, $import) => $chunks->merge(
76-
$resolveImportChunks($manifest[$import])
77-
),
78-
collect([$chunk])
79-
)
80-
->merge(collect($chunk['css'] ?? [])->map(
81-
fn ($css) => collect($manifest)->first(fn ($chunk) => $chunk['file'] === $css) ?? [
82-
'file' => $css,
83-
],
84-
));
85-
})
86-
->map(function ($chunk) use ($buildDirectory, $manifest) {
87-
return collect([
88-
...$this->resolvePreloadTagAttributes(
89-
$chunk['src'] ?? null,
90-
$url = $this->assetPath("{$buildDirectory}/{$chunk['file']}"),
91-
$chunk,
92-
$manifest,
93-
),
94-
'rel' => 'prefetch',
95-
'href' => $url,
96-
])->reject(
97-
fn ($value) => in_array($value, [null, false], true)
98-
)->mapWithKeys(fn ($value, $key) => [
99-
$key = (is_int($key) ? $value : $key) => $value === true ? $key : $value,
100-
])->all();
101-
})
102-
->reject(fn ($attributes) => isset($this->preloadedAssets[$attributes['href']])))
103-
->unique('href')
104-
->values()
105-
->pipe(fn ($assets) => with(Js::from($assets), fn ($assets) => match ($this->prefetchStrategy) {
106-
'waterfall' => new HtmlString($base.<<<HTML
107-
108-
<script>
109-
window.addEventListener('load', () => window.setTimeout(() => {
110-
const linkTemplate = document.createElement('link')
111-
linkTemplate.rel = 'prefetch'
112-
113-
const makeLink = (asset) => {
114-
const link = linkTemplate.cloneNode()
115-
116-
Object.keys(asset).forEach((attribute) => {
117-
link.setAttribute(attribute, asset[attribute])
118-
})
119-
120-
return link
121-
}
122-
123-
const loadNext = (assets, count) => window.setTimeout(() => {
124-
const fragment = new DocumentFragment
125-
126-
while (count > 0) {
127-
const link = makeLink(assets.shift())
128-
fragment.append(link)
129-
count--
130-
131-
if (assets.length) {
132-
link.onload = () => loadNext(assets, 1)
133-
link.error = () => loadNext(assets, 1)
134-
}
135-
}
136-
137-
document.head.append(fragment)
138-
})
139-
140-
loadNext({$assets}, {$this->prefetchChunks})
141-
}))
142-
</script>
143-
HTML),
144-
'aggressive' => new HtmlString($base.<<<HTML
145-
146-
<script>
147-
window.addEventListener('load', () => window.setTimeout(() => {
148-
const linkTemplate = document.createElement('link')
149-
linkTemplate.rel = 'prefetch'
150-
151-
const makeLink = (asset) => {
152-
const link = linkTemplate.cloneNode()
153-
154-
Object.keys(asset).forEach((attribute) => {
155-
link.setAttribute(attribute, asset[attribute])
156-
})
157-
158-
return link
159-
}
160-
161-
const fragment = new DocumentFragment
162-
{$assets}.forEach((asset) => fragment.append(makeLink(asset)))
163-
document.head.append(fragment)
164-
}))
165-
</script>
166-
HTML),
167-
}));
168-
}
169-
});
16+
//
17017
}
17118

17219
/**

playgrounds/svelte5/resources/js/ssr.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import { createInertiaApp } from '@inertiajs/svelte'
1+
import { createInertiaApp, type ResolvedComponent } from '@inertiajs/svelte'
22
import createServer from '@inertiajs/svelte/server'
3-
import { ResolvedComponent } from '@inertiajs/svelte'
43

54
createServer((page) =>
65
createInertiaApp({
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { createInertiaApp } from '@inertiajs/svelte'
2+
import type { AppCallback } from '@inertiajs/svelte/server'
3+
4+
export const render: AppCallback = (page) =>
5+
createInertiaApp({
6+
page,
7+
resolve: (name) => import(`./Pages/${name}.svelte`),
8+
})

playgrounds/svelte5/vite.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { svelte } from '@sveltejs/vite-plugin-svelte'
22
import laravel from 'laravel-vite-plugin'
33
import { defineConfig } from 'vite'
4+
import inertia from '@inertiajs/core/vite';
45

56
export default defineConfig({
67
plugins: [
@@ -9,6 +10,9 @@ export default defineConfig({
910
ssr: 'resources/js/ssr.ts',
1011
refresh: true,
1112
}),
13+
inertia({
14+
renderer: 'resources/js/viteSsr.ts',
15+
}),
1216
svelte(),
1317
],
1418
})

0 commit comments

Comments
 (0)