create-vite-extra 4.0.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +20 -7
- package/package.json +1 -1
- package/template-deno-lit/deno.json +1 -1
- package/template-deno-lit-ts/deno.json +1 -1
- package/template-deno-preact/deno.json +2 -2
- package/template-deno-preact-ts/deno.json +2 -2
- package/template-deno-react/deno.json +6 -6
- package/template-deno-react-ts/deno.json +6 -6
- package/template-deno-solid/deno.json +3 -3
- package/template-deno-solid-ts/deno.json +3 -3
- package/template-deno-svelte/deno.json +3 -3
- package/template-deno-svelte-ts/deno.json +3 -3
- package/template-deno-vanilla/deno.json +1 -1
- package/template-deno-vanilla-ts/deno.json +1 -1
- package/template-deno-vue/deno.json +3 -3
- package/template-deno-vue-ts/deno.json +3 -3
- package/template-library/package.json +1 -1
- package/template-library-ts/package.json +2 -2
- package/template-ssr-preact/package.json +6 -6
- package/template-ssr-preact-ts/package.json +8 -8
- package/template-ssr-react/package.json +9 -9
- package/template-ssr-react-streaming/index.html +1 -1
- package/template-ssr-react-streaming/package.json +7 -7
- package/template-ssr-react-streaming/server.js +17 -6
- package/template-ssr-react-streaming/src/App.jsx +2 -2
- package/template-ssr-react-streaming/src/entry-server.jsx +20 -0
- package/template-ssr-react-streaming-ts/index.html +1 -1
- package/template-ssr-react-streaming-ts/package.json +11 -11
- package/template-ssr-react-streaming-ts/server.js +17 -6
- package/template-ssr-react-streaming-ts/src/App.tsx +2 -2
- package/template-ssr-react-streaming-ts/src/entry-server.tsx +20 -0
- package/template-ssr-react-streaming-ts/src/vite-env.d.ts +8 -0
- package/template-ssr-react-ts/package.json +11 -11
- package/template-ssr-solid/package.json +6 -6
- package/template-ssr-solid-ts/package.json +7 -7
- package/template-ssr-svelte/package.json +6 -6
- package/template-ssr-svelte-ts/package.json +10 -10
- package/template-ssr-transform/package.json +1 -1
- package/template-ssr-vanilla/package.json +4 -4
- package/template-ssr-vanilla-ts/package.json +6 -6
- package/template-ssr-vue/package.json +6 -6
- package/template-ssr-vue-streaming/package.json +6 -6
- package/template-ssr-vue-streaming-ts/package.json +9 -9
- package/template-ssr-vue-ts/package.json +9 -9
package/index.js
CHANGED
|
@@ -23,7 +23,10 @@ const {
|
|
|
23
23
|
|
|
24
24
|
// Avoids autoconversion to number of the project name by defining that the args
|
|
25
25
|
// non associated with an option ( _ ) needs to be parsed as a string. See #4606
|
|
26
|
-
const argv = minimist(process.argv.slice(2), {
|
|
26
|
+
const argv = minimist(process.argv.slice(2), {
|
|
27
|
+
string: ['_'],
|
|
28
|
+
boolean: ['overwrite'],
|
|
29
|
+
})
|
|
27
30
|
const cwd = process.cwd()
|
|
28
31
|
|
|
29
32
|
const FRAMEWORKS = [
|
|
@@ -335,9 +338,14 @@ const FRAMEWORKS = [
|
|
|
335
338
|
},
|
|
336
339
|
]
|
|
337
340
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
+
function flattenVariants(framework) {
|
|
342
|
+
if (framework.variants) {
|
|
343
|
+
return framework.variants.flatMap((variant) => flattenVariants(variant))
|
|
344
|
+
}
|
|
345
|
+
return [framework.name]
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const TEMPLATES = FRAMEWORKS.flatMap(flattenVariants)
|
|
341
349
|
|
|
342
350
|
const renameFiles = {
|
|
343
351
|
_gitignore: '.gitignore',
|
|
@@ -368,8 +376,13 @@ async function init() {
|
|
|
368
376
|
},
|
|
369
377
|
{
|
|
370
378
|
type: () =>
|
|
371
|
-
|
|
379
|
+
argv.overwrite
|
|
380
|
+
? null
|
|
381
|
+
: !fs.existsSync(targetDir) || isEmpty(targetDir)
|
|
382
|
+
? null
|
|
383
|
+
: 'confirm',
|
|
372
384
|
name: 'overwrite',
|
|
385
|
+
initial: argv.overwrite ? true : false,
|
|
373
386
|
message: () =>
|
|
374
387
|
(targetDir === '.'
|
|
375
388
|
? 'Current directory'
|
|
@@ -639,14 +652,14 @@ function setupReactSwc(root, { isTs, isDeno }) {
|
|
|
639
652
|
editFile(path.resolve(root, 'deno.json'), (content) => {
|
|
640
653
|
return content.replace(
|
|
641
654
|
/"@vitejs\/plugin-react": ".+?"/,
|
|
642
|
-
`"@vitejs/plugin-react-swc": "npm:@vitejs/plugin-react-swc@^
|
|
655
|
+
`"@vitejs/plugin-react-swc": "npm:@vitejs/plugin-react-swc@^4.0.1"`,
|
|
643
656
|
)
|
|
644
657
|
})
|
|
645
658
|
} else {
|
|
646
659
|
editFile(path.resolve(root, 'package.json'), (content) => {
|
|
647
660
|
return content.replace(
|
|
648
661
|
/"@vitejs\/plugin-react": ".+?"/,
|
|
649
|
-
`"@vitejs/plugin-react-swc": "^
|
|
662
|
+
`"@vitejs/plugin-react-swc": "^4.0.1"`,
|
|
650
663
|
)
|
|
651
664
|
})
|
|
652
665
|
}
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"imports": {
|
|
14
14
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
15
15
|
"@preact/preset-vite": "npm:@preact/preset-vite@^2.10.2",
|
|
16
|
-
"preact": "npm:preact@^10.
|
|
17
|
-
"vite": "npm:vite@^7.
|
|
16
|
+
"preact": "npm:preact@^10.27.2",
|
|
17
|
+
"vite": "npm:vite@^7.1.5"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"imports": {
|
|
14
14
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
15
15
|
"@preact/preset-vite": "npm:@preact/preset-vite@^2.10.2",
|
|
16
|
-
"preact": "npm:preact@^10.
|
|
17
|
-
"vite": "npm:vite@^7.
|
|
16
|
+
"preact": "npm:preact@^10.27.2",
|
|
17
|
+
"vite": "npm:vite@^7.1.5"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"imports": {
|
|
15
15
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
16
|
-
"@types/react": "npm:@types/react@^19.1.
|
|
17
|
-
"@types/react-dom": "npm:@types/react-dom@^19.1.
|
|
18
|
-
"@vitejs/plugin-react": "npm:@vitejs/plugin-react@^
|
|
19
|
-
"react": "npm:react@^19.1.
|
|
20
|
-
"react-dom": "npm:react-dom@^19.1.
|
|
21
|
-
"vite": "npm:vite@^7.
|
|
16
|
+
"@types/react": "npm:@types/react@^19.1.13",
|
|
17
|
+
"@types/react-dom": "npm:@types/react-dom@^19.1.9",
|
|
18
|
+
"@vitejs/plugin-react": "npm:@vitejs/plugin-react@^5.0.2",
|
|
19
|
+
"react": "npm:react@^19.1.1",
|
|
20
|
+
"react-dom": "npm:react-dom@^19.1.1",
|
|
21
|
+
"vite": "npm:vite@^7.1.5"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -13,11 +13,11 @@
|
|
|
13
13
|
},
|
|
14
14
|
"imports": {
|
|
15
15
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
16
|
-
"@types/react": "npm:@types/react@^19.1.
|
|
17
|
-
"@types/react-dom": "npm:@types/react-dom@^19.1.
|
|
18
|
-
"@vitejs/plugin-react": "npm:@vitejs/plugin-react@^
|
|
19
|
-
"react": "npm:react@^19.1.
|
|
20
|
-
"react-dom": "npm:react-dom@^19.1.
|
|
21
|
-
"vite": "npm:vite@^7.
|
|
16
|
+
"@types/react": "npm:@types/react@^19.1.13",
|
|
17
|
+
"@types/react-dom": "npm:@types/react-dom@^19.1.9",
|
|
18
|
+
"@vitejs/plugin-react": "npm:@vitejs/plugin-react@^5.0.2",
|
|
19
|
+
"react": "npm:react@^19.1.1",
|
|
20
|
+
"react-dom": "npm:react-dom@^19.1.1",
|
|
21
|
+
"vite": "npm:vite@^7.1.5"
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"imports": {
|
|
14
14
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
15
|
-
"solid-js": "npm:solid-js@^1.9.
|
|
16
|
-
"vite": "npm:vite@^7.
|
|
17
|
-
"vite-plugin-solid": "npm:vite-plugin-solid@^2.11.
|
|
15
|
+
"solid-js": "npm:solid-js@^1.9.9",
|
|
16
|
+
"vite": "npm:vite@^7.1.5",
|
|
17
|
+
"vite-plugin-solid": "npm:vite-plugin-solid@^2.11.8"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
},
|
|
13
13
|
"imports": {
|
|
14
14
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
15
|
-
"solid-js": "npm:solid-js@^1.9.
|
|
16
|
-
"vite": "npm:vite@^7.
|
|
17
|
-
"vite-plugin-solid": "npm:vite-plugin-solid@^2.11.
|
|
15
|
+
"solid-js": "npm:solid-js@^1.9.9",
|
|
16
|
+
"vite": "npm:vite@^7.1.5",
|
|
17
|
+
"vite-plugin-solid": "npm:vite-plugin-solid@^2.11.8"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"imports": {
|
|
12
12
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
13
|
-
"@sveltejs/vite-plugin-svelte": "npm:@sveltejs/vite-plugin-svelte@^
|
|
14
|
-
"svelte": "npm:svelte@^5.
|
|
15
|
-
"vite": "npm:vite@^7.
|
|
13
|
+
"@sveltejs/vite-plugin-svelte": "npm:@sveltejs/vite-plugin-svelte@^6.2.0",
|
|
14
|
+
"svelte": "npm:svelte@^5.38.10",
|
|
15
|
+
"vite": "npm:vite@^7.1.5"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"imports": {
|
|
12
12
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
13
|
-
"@sveltejs/vite-plugin-svelte": "npm:@sveltejs/vite-plugin-svelte@^
|
|
14
|
-
"svelte": "npm:svelte@^5.
|
|
15
|
-
"vite": "npm:vite@^7.
|
|
13
|
+
"@sveltejs/vite-plugin-svelte": "npm:@sveltejs/vite-plugin-svelte@^6.2.0",
|
|
14
|
+
"svelte": "npm:svelte@^5.38.10",
|
|
15
|
+
"vite": "npm:vite@^7.1.5"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"imports": {
|
|
12
12
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
13
|
-
"@vitejs/plugin-vue": "npm:@vitejs/plugin-vue@^6.0.
|
|
14
|
-
"vite": "npm:vite@^7.
|
|
15
|
-
"vue": "npm:vue@^3.5.
|
|
13
|
+
"@vitejs/plugin-vue": "npm:@vitejs/plugin-vue@^6.0.1",
|
|
14
|
+
"vite": "npm:vite@^7.1.5",
|
|
15
|
+
"vue": "npm:vue@^3.5.21"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
},
|
|
11
11
|
"imports": {
|
|
12
12
|
"@deno/vite-plugin": "npm:@deno/vite-plugin@^1.0.5",
|
|
13
|
-
"@vitejs/plugin-vue": "npm:@vitejs/plugin-vue@^6.0.
|
|
14
|
-
"vite": "npm:vite@^7.
|
|
15
|
-
"vue": "npm:vue@^3.5.
|
|
13
|
+
"@vitejs/plugin-vue": "npm:@vitejs/plugin-vue@^6.0.1",
|
|
14
|
+
"vite": "npm:vite@^7.1.5",
|
|
15
|
+
"vue": "npm:vue@^3.5.21"
|
|
16
16
|
}
|
|
17
17
|
}
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"preact": "^10.
|
|
17
|
-
"preact-render-to-string": "^6.
|
|
18
|
-
"sirv": "^3.0.
|
|
16
|
+
"preact": "^10.27.2",
|
|
17
|
+
"preact-render-to-string": "^6.6.1",
|
|
18
|
+
"sirv": "^3.0.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@preact/preset-vite": "^2.10.2",
|
|
22
|
-
"cross-env": "^
|
|
23
|
-
"vite": "^7.
|
|
22
|
+
"cross-env": "^10.0.0",
|
|
23
|
+
"vite": "^7.1.5"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"preact": "^10.
|
|
17
|
-
"preact-render-to-string": "^6.
|
|
18
|
-
"sirv": "^3.0.
|
|
16
|
+
"preact": "^10.27.2",
|
|
17
|
+
"preact-render-to-string": "^6.6.1",
|
|
18
|
+
"sirv": "^3.0.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@preact/preset-vite": "^2.10.2",
|
|
22
22
|
"@types/express": "^5.0.3",
|
|
23
|
-
"@types/node": "^24.
|
|
24
|
-
"cross-env": "^
|
|
25
|
-
"typescript": "~5.
|
|
26
|
-
"vite": "^7.
|
|
23
|
+
"@types/node": "^24.5.1",
|
|
24
|
+
"cross-env": "^10.0.0",
|
|
25
|
+
"typescript": "~5.9.2",
|
|
26
|
+
"vite": "^7.1.5"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"react": "^19.1.
|
|
17
|
-
"react-dom": "^19.1.
|
|
18
|
-
"sirv": "^3.0.
|
|
16
|
+
"react": "^19.1.1",
|
|
17
|
+
"react-dom": "^19.1.1",
|
|
18
|
+
"sirv": "^3.0.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@types/react": "^19.1.
|
|
22
|
-
"@types/react-dom": "^19.1.
|
|
23
|
-
"@vitejs/plugin-react": "^
|
|
24
|
-
"cross-env": "^
|
|
25
|
-
"vite": "^7.
|
|
21
|
+
"@types/react": "^19.1.13",
|
|
22
|
+
"@types/react-dom": "^19.1.9",
|
|
23
|
+
"@vitejs/plugin-react": "^5.0.2",
|
|
24
|
+
"cross-env": "^10.0.0",
|
|
25
|
+
"vite": "^7.1.5"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"react": "^19.1.
|
|
17
|
-
"react-dom": "^19.1.
|
|
18
|
-
"sirv": "^3.0.
|
|
16
|
+
"react": "^19.1.1",
|
|
17
|
+
"react-dom": "^19.1.1",
|
|
18
|
+
"sirv": "^3.0.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@vitejs/plugin-react": "^
|
|
22
|
-
"cross-env": "^
|
|
23
|
-
"vite": "^7.
|
|
21
|
+
"@vitejs/plugin-react": "^5.0.2",
|
|
22
|
+
"cross-env": "^10.0.0",
|
|
23
|
+
"vite": "^7.1.5"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -65,21 +65,32 @@ app.use('*all', async (req, res) => {
|
|
|
65
65
|
res.status(didError ? 500 : 200)
|
|
66
66
|
res.set({ 'Content-Type': 'text/html' })
|
|
67
67
|
|
|
68
|
+
const [htmlStart, htmlEnd] = template.split(`<!--app-html-->`)
|
|
69
|
+
let htmlEnded = false
|
|
70
|
+
|
|
68
71
|
const transformStream = new Transform({
|
|
69
72
|
transform(chunk, encoding, callback) {
|
|
70
|
-
|
|
73
|
+
// See entry-server.jsx for more details of this code
|
|
74
|
+
if (!htmlEnded) {
|
|
75
|
+
chunk = chunk.toString()
|
|
76
|
+
if (chunk.endsWith('<vite-streaming-end></vite-streaming-end>')) {
|
|
77
|
+
res.write(chunk.slice(0, -41) + htmlEnd, 'utf-8')
|
|
78
|
+
} else {
|
|
79
|
+
res.write(chunk, 'utf-8')
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
res.write(chunk, encoding)
|
|
83
|
+
}
|
|
71
84
|
callback()
|
|
72
85
|
},
|
|
73
86
|
})
|
|
74
87
|
|
|
75
|
-
const [htmlStart, htmlEnd] = template.split(`<!--app-html-->`)
|
|
76
|
-
|
|
77
|
-
res.write(htmlStart)
|
|
78
|
-
|
|
79
88
|
transformStream.on('finish', () => {
|
|
80
|
-
res.end(
|
|
89
|
+
res.end()
|
|
81
90
|
})
|
|
82
91
|
|
|
92
|
+
res.write(htmlStart)
|
|
93
|
+
|
|
83
94
|
pipe(transformStream)
|
|
84
95
|
},
|
|
85
96
|
onError(error) {
|
|
@@ -7,7 +7,7 @@ const Card = lazy(() => import('./Card'))
|
|
|
7
7
|
|
|
8
8
|
function App() {
|
|
9
9
|
return (
|
|
10
|
-
|
|
10
|
+
<main>
|
|
11
11
|
<div>
|
|
12
12
|
<a href="https://vite.dev" target="_blank">
|
|
13
13
|
<img src="/vite.svg" className="logo" alt="Vite logo" />
|
|
@@ -25,7 +25,7 @@ function App() {
|
|
|
25
25
|
<p className="read-the-docs">
|
|
26
26
|
Click on the Vite and React logos to learn more
|
|
27
27
|
</p>
|
|
28
|
-
|
|
28
|
+
</main>
|
|
29
29
|
)
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -2,6 +2,25 @@ import { StrictMode } from 'react'
|
|
|
2
2
|
import { renderToPipeableStream } from 'react-dom/server'
|
|
3
3
|
import App from './App'
|
|
4
4
|
|
|
5
|
+
/*
|
|
6
|
+
React SSR streaming with Suspense works by adding JS code to the end of the
|
|
7
|
+
HTML to update the suspended element in the client side. However, there are 2
|
|
8
|
+
issues when integrating it in Vite with React's `renderToPipeableStream` API:
|
|
9
|
+
|
|
10
|
+
1. The API requires a parent element for Suspense for the above behavior to
|
|
11
|
+
work, otherwise suspended elements will be awaited in-place, resulting in
|
|
12
|
+
slow streaming.
|
|
13
|
+
|
|
14
|
+
2. The API stalls the stream to later append the JS code, causing us to unable
|
|
15
|
+
to add the trailing HTML code (the part after `<!--app-html-->` in index.html).
|
|
16
|
+
This is because React assumes full control of the entire HTML output, which
|
|
17
|
+
isn't feasible here as Vite requires HTML files as entrypoints and for bundling.
|
|
18
|
+
|
|
19
|
+
The solution here is to ensure a parent element (`<main>` in `<App/>`), and a
|
|
20
|
+
custom element (`<vite-streaming-end>`) to detect when React has finished
|
|
21
|
+
rendering its main content so we can render Vite's HTML after it.
|
|
22
|
+
*/
|
|
23
|
+
|
|
5
24
|
/**
|
|
6
25
|
* @param {string} _url
|
|
7
26
|
* @param {import('react-dom/server').RenderToPipeableStreamOptions} [options]
|
|
@@ -10,6 +29,7 @@ export function render(_url, options) {
|
|
|
10
29
|
return renderToPipeableStream(
|
|
11
30
|
<StrictMode>
|
|
12
31
|
<App />
|
|
32
|
+
<vite-streaming-end></vite-streaming-end>
|
|
13
33
|
</StrictMode>,
|
|
14
34
|
options,
|
|
15
35
|
)
|
|
@@ -11,20 +11,20 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"react": "^19.1.
|
|
17
|
-
"react-dom": "^19.1.
|
|
18
|
-
"sirv": "^3.0.
|
|
16
|
+
"react": "^19.1.1",
|
|
17
|
+
"react-dom": "^19.1.1",
|
|
18
|
+
"sirv": "^3.0.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/express": "^5.0.3",
|
|
22
|
-
"@types/node": "^24.
|
|
23
|
-
"@types/react": "^19.1.
|
|
24
|
-
"@types/react-dom": "^19.1.
|
|
25
|
-
"@vitejs/plugin-react": "^
|
|
26
|
-
"cross-env": "^
|
|
27
|
-
"typescript": "~5.
|
|
28
|
-
"vite": "^7.
|
|
22
|
+
"@types/node": "^24.5.1",
|
|
23
|
+
"@types/react": "^19.1.13",
|
|
24
|
+
"@types/react-dom": "^19.1.9",
|
|
25
|
+
"@vitejs/plugin-react": "^5.0.2",
|
|
26
|
+
"cross-env": "^10.0.0",
|
|
27
|
+
"typescript": "~5.9.2",
|
|
28
|
+
"vite": "^7.1.5"
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -65,21 +65,32 @@ app.use('*all', async (req, res) => {
|
|
|
65
65
|
res.status(didError ? 500 : 200)
|
|
66
66
|
res.set({ 'Content-Type': 'text/html' })
|
|
67
67
|
|
|
68
|
+
const [htmlStart, htmlEnd] = template.split(`<!--app-html-->`)
|
|
69
|
+
let htmlEnded = false
|
|
70
|
+
|
|
68
71
|
const transformStream = new Transform({
|
|
69
72
|
transform(chunk, encoding, callback) {
|
|
70
|
-
|
|
73
|
+
// See entry-server.tsx for more details of this code
|
|
74
|
+
if (!htmlEnded) {
|
|
75
|
+
chunk = chunk.toString()
|
|
76
|
+
if (chunk.endsWith('<vite-streaming-end></vite-streaming-end>')) {
|
|
77
|
+
res.write(chunk.slice(0, -41) + htmlEnd, 'utf-8')
|
|
78
|
+
} else {
|
|
79
|
+
res.write(chunk, 'utf-8')
|
|
80
|
+
}
|
|
81
|
+
} else {
|
|
82
|
+
res.write(chunk, encoding)
|
|
83
|
+
}
|
|
71
84
|
callback()
|
|
72
85
|
},
|
|
73
86
|
})
|
|
74
87
|
|
|
75
|
-
const [htmlStart, htmlEnd] = template.split(`<!--app-html-->`)
|
|
76
|
-
|
|
77
|
-
res.write(htmlStart)
|
|
78
|
-
|
|
79
88
|
transformStream.on('finish', () => {
|
|
80
|
-
res.end(
|
|
89
|
+
res.end()
|
|
81
90
|
})
|
|
82
91
|
|
|
92
|
+
res.write(htmlStart)
|
|
93
|
+
|
|
83
94
|
pipe(transformStream)
|
|
84
95
|
},
|
|
85
96
|
onError(error) {
|
|
@@ -7,7 +7,7 @@ const Card = lazy(() => import('./Card'))
|
|
|
7
7
|
|
|
8
8
|
function App() {
|
|
9
9
|
return (
|
|
10
|
-
|
|
10
|
+
<main>
|
|
11
11
|
<div>
|
|
12
12
|
<a href="https://vite.dev" target="_blank">
|
|
13
13
|
<img src="/vite.svg" className="logo" alt="Vite logo" />
|
|
@@ -25,7 +25,7 @@ function App() {
|
|
|
25
25
|
<p className="read-the-docs">
|
|
26
26
|
Click on the Vite and React logos to learn more
|
|
27
27
|
</p>
|
|
28
|
-
|
|
28
|
+
</main>
|
|
29
29
|
)
|
|
30
30
|
}
|
|
31
31
|
|
|
@@ -5,10 +5,30 @@ import {
|
|
|
5
5
|
} from 'react-dom/server'
|
|
6
6
|
import App from './App'
|
|
7
7
|
|
|
8
|
+
/*
|
|
9
|
+
React SSR streaming with Suspense works by adding JS code to the end of the
|
|
10
|
+
HTML to update the suspended element in the client side. However, there are 2
|
|
11
|
+
issues when integrating it in Vite with React's `renderToPipeableStream` API:
|
|
12
|
+
|
|
13
|
+
1. The API requires a parent element for Suspense for the above behavior to
|
|
14
|
+
work, otherwise suspended elements will be awaited in-place, resulting in
|
|
15
|
+
slow streaming.
|
|
16
|
+
|
|
17
|
+
2. The API stalls the stream to later append the JS code, causing us to unable
|
|
18
|
+
to add the trailing HTML code (the part after `<!--app-html-->` in index.html).
|
|
19
|
+
This is because React assumes full control of the entire HTML output, which
|
|
20
|
+
isn't feasible here as Vite requires HTML files as entrypoints and for bundling.
|
|
21
|
+
|
|
22
|
+
The solution here is to ensure a parent element (`<main>` in `<App/>`), and a
|
|
23
|
+
custom element (`<vite-streaming-end>`) to detect when React has finished
|
|
24
|
+
rendering its main content so we can render Vite's HTML after it.
|
|
25
|
+
*/
|
|
26
|
+
|
|
8
27
|
export function render(_url: string, options?: RenderToPipeableStreamOptions) {
|
|
9
28
|
return renderToPipeableStream(
|
|
10
29
|
<StrictMode>
|
|
11
30
|
<App />
|
|
31
|
+
<vite-streaming-end></vite-streaming-end>
|
|
12
32
|
</StrictMode>,
|
|
13
33
|
options,
|
|
14
34
|
)
|
|
@@ -11,20 +11,20 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"react": "^19.1.
|
|
17
|
-
"react-dom": "^19.1.
|
|
18
|
-
"sirv": "^3.0.
|
|
16
|
+
"react": "^19.1.1",
|
|
17
|
+
"react-dom": "^19.1.1",
|
|
18
|
+
"sirv": "^3.0.2"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/express": "^5.0.3",
|
|
22
|
-
"@types/node": "^24.
|
|
23
|
-
"@types/react": "^19.1.
|
|
24
|
-
"@types/react-dom": "^19.1.
|
|
25
|
-
"@vitejs/plugin-react": "^
|
|
26
|
-
"cross-env": "^
|
|
27
|
-
"typescript": "~5.
|
|
28
|
-
"vite": "^7.
|
|
22
|
+
"@types/node": "^24.5.1",
|
|
23
|
+
"@types/react": "^19.1.13",
|
|
24
|
+
"@types/react-dom": "^19.1.9",
|
|
25
|
+
"@vitejs/plugin-react": "^5.0.2",
|
|
26
|
+
"cross-env": "^10.0.0",
|
|
27
|
+
"typescript": "~5.9.2",
|
|
28
|
+
"vite": "^7.1.5"
|
|
29
29
|
}
|
|
30
30
|
}
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
17
|
-
"solid-js": "^1.9.
|
|
16
|
+
"sirv": "^3.0.2",
|
|
17
|
+
"solid-js": "^1.9.9"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"cross-env": "^
|
|
21
|
-
"vite": "^7.
|
|
22
|
-
"vite-plugin-solid": "^2.11.
|
|
20
|
+
"cross-env": "^10.0.0",
|
|
21
|
+
"vite": "^7.1.5",
|
|
22
|
+
"vite-plugin-solid": "^2.11.8"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -11,16 +11,16 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
17
|
-
"solid-js": "^1.9.
|
|
16
|
+
"sirv": "^3.0.2",
|
|
17
|
+
"solid-js": "^1.9.9"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@types/express": "^5.0.3",
|
|
21
|
-
"@types/node": "^24.
|
|
22
|
-
"cross-env": "^
|
|
23
|
-
"vite": "^7.
|
|
24
|
-
"vite-plugin-solid": "^2.11.
|
|
21
|
+
"@types/node": "^24.5.1",
|
|
22
|
+
"cross-env": "^10.0.0",
|
|
23
|
+
"vite": "^7.1.5",
|
|
24
|
+
"vite-plugin-solid": "^2.11.8"
|
|
25
25
|
}
|
|
26
26
|
}
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
16
|
+
"sirv": "^3.0.2"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
20
|
-
"cross-env": "^
|
|
21
|
-
"svelte": "^5.
|
|
22
|
-
"vite": "^7.
|
|
19
|
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
|
|
20
|
+
"cross-env": "^10.0.0",
|
|
21
|
+
"svelte": "^5.38.10",
|
|
22
|
+
"vite": "^7.1.5"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -12,20 +12,20 @@
|
|
|
12
12
|
"check": "svelte-check"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"compression": "^1.8.
|
|
15
|
+
"compression": "^1.8.1",
|
|
16
16
|
"express": "^5.1.0",
|
|
17
|
-
"sirv": "^3.0.
|
|
17
|
+
"sirv": "^3.0.2"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@sveltejs/vite-plugin-svelte": "^
|
|
21
|
-
"@tsconfig/svelte": "^5.0.
|
|
20
|
+
"@sveltejs/vite-plugin-svelte": "^6.2.0",
|
|
21
|
+
"@tsconfig/svelte": "^5.0.5",
|
|
22
22
|
"@types/express": "^5.0.3",
|
|
23
|
-
"@types/node": "^24.
|
|
24
|
-
"cross-env": "^
|
|
25
|
-
"svelte": "^5.
|
|
26
|
-
"svelte-check": "^4.
|
|
23
|
+
"@types/node": "^24.5.1",
|
|
24
|
+
"cross-env": "^10.0.0",
|
|
25
|
+
"svelte": "^5.38.10",
|
|
26
|
+
"svelte-check": "^4.3.1",
|
|
27
27
|
"tslib": "^2.8.1",
|
|
28
|
-
"typescript": "~5.
|
|
29
|
-
"vite": "^7.
|
|
28
|
+
"typescript": "~5.9.2",
|
|
29
|
+
"vite": "^7.1.5"
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -11,12 +11,12 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
16
|
+
"sirv": "^3.0.2"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"cross-env": "^
|
|
20
|
-
"vite": "^7.
|
|
19
|
+
"cross-env": "^10.0.0",
|
|
20
|
+
"vite": "^7.1.5"
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -11,15 +11,15 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
16
|
+
"sirv": "^3.0.2"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@types/express": "^5.0.3",
|
|
20
|
-
"@types/node": "^24.
|
|
21
|
-
"cross-env": "^
|
|
22
|
-
"typescript": "~5.
|
|
23
|
-
"vite": "^7.
|
|
20
|
+
"@types/node": "^24.5.1",
|
|
21
|
+
"cross-env": "^10.0.0",
|
|
22
|
+
"typescript": "~5.9.2",
|
|
23
|
+
"vite": "^7.1.5"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
17
|
-
"vue": "^3.5.
|
|
16
|
+
"sirv": "^3.0.2",
|
|
17
|
+
"vue": "^3.5.21"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
21
|
-
"cross-env": "^
|
|
22
|
-
"vite": "^7.
|
|
20
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
21
|
+
"cross-env": "^10.0.0",
|
|
22
|
+
"vite": "^7.1.5"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -11,14 +11,14 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
17
|
-
"vue": "^3.5.
|
|
16
|
+
"sirv": "^3.0.2",
|
|
17
|
+
"vue": "^3.5.21"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
21
|
-
"cross-env": "^
|
|
22
|
-
"vite": "^7.
|
|
20
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
21
|
+
"cross-env": "^10.0.0",
|
|
22
|
+
"vite": "^7.1.5"
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -11,18 +11,18 @@
|
|
|
11
11
|
"preview": "cross-env NODE_ENV=production node server"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"compression": "^1.8.
|
|
14
|
+
"compression": "^1.8.1",
|
|
15
15
|
"express": "^5.1.0",
|
|
16
|
-
"sirv": "^3.0.
|
|
17
|
-
"vue": "^3.5.
|
|
16
|
+
"sirv": "^3.0.2",
|
|
17
|
+
"vue": "^3.5.21"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
20
|
"@types/express": "^5.0.3",
|
|
21
|
-
"@types/node": "^24.
|
|
22
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
23
|
-
"cross-env": "^
|
|
24
|
-
"typescript": "~5.
|
|
25
|
-
"vite": "^7.
|
|
26
|
-
"vue-tsc": "^
|
|
21
|
+
"@types/node": "^24.5.1",
|
|
22
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
23
|
+
"cross-env": "^10.0.0",
|
|
24
|
+
"typescript": "~5.9.2",
|
|
25
|
+
"vite": "^7.1.5",
|
|
26
|
+
"vue-tsc": "^3.0.7"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -12,18 +12,18 @@
|
|
|
12
12
|
"check": "vue-tsc"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"compression": "^1.8.
|
|
15
|
+
"compression": "^1.8.1",
|
|
16
16
|
"express": "^5.1.0",
|
|
17
|
-
"sirv": "^3.0.
|
|
18
|
-
"vue": "^3.5.
|
|
17
|
+
"sirv": "^3.0.2",
|
|
18
|
+
"vue": "^3.5.21"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
21
|
"@types/express": "^5.0.3",
|
|
22
|
-
"@types/node": "^24.
|
|
23
|
-
"@vitejs/plugin-vue": "^6.0.
|
|
24
|
-
"cross-env": "^
|
|
25
|
-
"typescript": "~5.
|
|
26
|
-
"vite": "^7.
|
|
27
|
-
"vue-tsc": "^
|
|
22
|
+
"@types/node": "^24.5.1",
|
|
23
|
+
"@vitejs/plugin-vue": "^6.0.1",
|
|
24
|
+
"cross-env": "^10.0.0",
|
|
25
|
+
"typescript": "~5.9.2",
|
|
26
|
+
"vite": "^7.1.5",
|
|
27
|
+
"vue-tsc": "^3.0.7"
|
|
28
28
|
}
|
|
29
29
|
}
|