@@ -4,14 +4,11 @@ import express from 'express'
4
4
import { createServer as createViteServer } from 'vite'
5
5
6
6
import { getProjectRoutes } from '@redwoodjs/internal/dist/routes'
7
- import { getAppRouteHook , getConfig , getPaths } from '@redwoodjs/project-config'
8
- import { matchPath } from '@redwoodjs/router'
9
- import type { TagDescriptor } from '@redwoodjs/web'
7
+ import { getConfig , getPaths } from '@redwoodjs/project-config'
10
8
9
+ import { createReactStreamingHandler } from './streaming/createReactStreamingHandler'
11
10
import { registerFwGlobals } from './streaming/registerGlobals'
12
- import { reactRenderToStream } from './streaming/streamHelpers'
13
- import { loadAndRunRouteHooks } from './streaming/triggerRouteHooks'
14
- import { ensureProcessDirWeb , stripQueryStringAndHashFromPath } from './utils'
11
+ import { ensureProcessDirWeb } from './utils'
15
12
16
13
// TODO (STREAMING) Just so it doesn't error out. Not sure how to handle this.
17
14
globalThis . __REDWOOD__PRERENDER_PAGES = { }
@@ -24,14 +21,24 @@ async function createServer() {
24
21
const app = express ( )
25
22
const rwPaths = getPaths ( )
26
23
24
+ // ~~~ Dev time validations ~~~~
27
25
// TODO (STREAMING) When Streaming is released Vite will be the only bundler,
28
26
// and this file should always exist. So the error message needs to change
29
27
// (or be removed perhaps)
28
+ if ( ! rwPaths . web . entryServer || ! rwPaths . web . entryClient ) {
29
+ throw new Error (
30
+ 'Vite entry points not found. Please check that your project has ' +
31
+ 'an entry.client.{jsx,tsx} and entry.server.{jsx,tsx} file in ' +
32
+ 'the web/src directory.'
33
+ )
34
+ }
35
+
30
36
if ( ! rwPaths . web . viteConfig ) {
31
37
throw new Error (
32
38
'Vite config not found. You need to setup your project with Vite using `yarn rw setup vite`'
33
39
)
34
40
}
41
+ // ~~~~ Dev time validations ~~~~
35
42
36
43
// Create Vite server in middleware mode and configure the app type as
37
44
// 'custom', disabling Vite's own HTML serving logic so parent server
@@ -47,89 +54,35 @@ async function createServer() {
47
54
// use vite's connect instance as middleware
48
55
app . use ( vite . middlewares )
49
56
50
- app . use ( '*' , async ( req , res , next ) => {
51
- const currentPathName = stripQueryStringAndHashFromPath ( req . originalUrl )
52
- globalThis . __REDWOOD__HELMET_CONTEXT = { }
53
-
54
- try {
55
- const routes = getProjectRoutes ( )
56
-
57
- // Do a simple match with regex, don't bother parsing params yet
58
- const currentRoute = routes . find ( ( route ) => {
59
- if ( ! route . matchRegexString ) {
60
- // This is the 404/NotFoundPage case
61
- return false
62
- }
63
-
64
- const matches = [
65
- ...currentPathName . matchAll ( new RegExp ( route . matchRegexString , 'g' ) ) ,
66
- ]
67
-
68
- return matches . length > 0
69
- } )
70
-
71
- let metaTags : TagDescriptor [ ] = [ ]
72
-
73
- if ( currentRoute ?. redirect ) {
74
- return res . redirect ( currentRoute . redirect . to )
75
- }
76
-
77
- if ( currentRoute ) {
78
- const parsedParams = currentRoute . hasParams
79
- ? matchPath ( currentRoute . path , currentPathName ) . params
80
- : undefined
81
-
82
- const routeHookOutput = await loadAndRunRouteHooks ( {
83
- paths : [ getAppRouteHook ( ) , currentRoute . routeHooks ] ,
84
- reqMeta : {
85
- req,
86
- parsedParams,
87
- } ,
88
- viteDevServer : vite , // because its dev
89
- } )
90
-
91
- metaTags = routeHookOutput . meta
92
- }
93
-
94
- if ( ! currentRoute ) {
95
- // TODO (STREAMING) do something
96
- }
97
-
98
- if ( ! rwPaths . web . entryServer || ! rwPaths . web . entryClient ) {
99
- throw new Error (
100
- 'Vite entry points not found. Please check that your project has ' +
101
- 'an entry.client.{jsx,tsx} and entry.server.{jsx,tsx} file in ' +
102
- 'the web/src directory.'
103
- )
104
- }
105
-
106
- // 3. Load the server entry. vite.ssrLoadModule automatically transforms
107
- // your ESM source code to be usable in Node.js! There is no bundling
108
- // required, and provides efficient invalidation similar to HMR.
109
- const { ServerEntry } = await vite . ssrLoadModule ( rwPaths . web . entryServer )
110
-
111
- const pageWithJs = currentRoute ?. renderMode !== 'html'
112
-
113
- res . setHeader ( 'content-type' , 'text/html; charset=utf-8' )
114
-
115
- reactRenderToStream ( {
116
- ServerEntry,
117
- currentPathName,
118
- metaTags,
119
- includeJs : pageWithJs ,
120
- res,
121
- } )
122
- } catch ( e ) {
123
- // TODO (STREAMING) Is this what we want to do?
124
- // send back a SPA page
125
- // res.status(200).set({ 'Content-Type': 'text/html' }).end(template)
126
-
127
- // If an error is caught, let Vite fix the stack trace so it maps back to
128
- // your actual source code.
129
- vite . ssrFixStacktrace ( e as any )
130
- next ( e )
57
+ const routes = getProjectRoutes ( )
58
+
59
+ // TODO (STREAMING) CSS is handled by Vite in dev mode, we don't need to
60
+ // worry about it in dev but..... it causes a flash of unstyled content.
61
+ // For now I'm just injecting index css here
62
+ // Look at collectStyles in packages/vite/src/fully-react/find-styles.ts
63
+ const FIXME_HardcodedIndexCss = [ 'index.css' ]
64
+
65
+ for ( const route of routes ) {
66
+ const routeHandler = await createReactStreamingHandler (
67
+ {
68
+ route,
69
+ clientEntryPath : rwPaths . web . entryClient as string ,
70
+ cssLinks : FIXME_HardcodedIndexCss ,
71
+ } ,
72
+ vite
73
+ )
74
+
75
+ // @TODO if it is a 404, hand over to 404 handler
76
+ if ( ! route . matchRegexString ) {
77
+ continue
131
78
}
132
- } )
79
+
80
+ const expressPathDef = route . hasParams
81
+ ? route . matchRegexString
82
+ : route . pathDefinition
83
+
84
+ app . get ( expressPathDef , routeHandler )
85
+ }
133
86
134
87
const port = getConfig ( ) . web . port
135
88
console . log ( `Started server on http://localhost:${ port } ` )
@@ -141,7 +94,9 @@ let devApp = createServer()
141
94
process . stdin . on ( 'data' , async ( data ) => {
142
95
const str = data . toString ( ) . trim ( ) . toLowerCase ( )
143
96
if ( str === 'rs' || str === 'restart' ) {
144
- ; ( await devApp ) . close ( )
145
- devApp = createServer ( )
97
+ console . log ( 'Restarting dev web server.....' )
98
+ ; ( await devApp ) . close ( ( ) => {
99
+ devApp = createServer ( )
100
+ } )
146
101
}
147
102
} )
0 commit comments