@@ -5,7 +5,10 @@ import { isRunnableDevEnvironment, type RunnableDevEnvironment } from 'vite';
55import { toFallbackType } from '../core/app/common.js' ;
66import { toRoutingStrategy } from '../core/app/entrypoints/index.js' ;
77import type { SSRManifest , SSRManifestCSP , SSRManifestI18n } from '../core/app/types.js' ;
8- import { ASTRO_VITE_ENVIRONMENT_NAMES } from '../core/constants.js' ;
8+ import {
9+ ASTRO_VITE_ENVIRONMENT_NAMES ,
10+ devPrerenderMiddlewareSymbol ,
11+ } from '../core/constants.js' ;
912import {
1013 getAlgorithm ,
1114 getDirectives ,
@@ -22,6 +25,7 @@ import { AstroError, AstroErrorData } from '../core/errors/index.js';
2225import type { Logger } from '../core/logger/core.js' ;
2326import { NOOP_MIDDLEWARE_FN } from '../core/middleware/noop-middleware.js' ;
2427import { createViteLoader } from '../core/module-loader/index.js' ;
28+ import { matchAllRoutes } from '../core/routing/match.js' ;
2529import { resolveMiddlewareMode } from '../integrations/adapter-utils.js' ;
2630import { SERIALIZED_MANIFEST_ID } from '../manifest/serialized.js' ;
2731import type { AstroSettings } from '../types/astro.js' ;
@@ -50,24 +54,41 @@ export default function createVitePluginAstroServer({
5054 return environment . name === ASTRO_VITE_ENVIRONMENT_NAMES . ssr ;
5155 } ,
5256 async configureServer ( viteServer ) {
53- // Cloudflare handles its own requests
57+ const ssrEnvironment = viteServer . environments [ ASTRO_VITE_ENVIRONMENT_NAMES . ssr ] ;
58+ const prerenderEnvironment = viteServer . environments [ ASTRO_VITE_ENVIRONMENT_NAMES . prerender ] ;
59+
60+ const runnableSsrEnvironment = isRunnableDevEnvironment ( ssrEnvironment )
61+ ? ( ssrEnvironment as RunnableDevEnvironment )
62+ : undefined ;
63+ const runnablePrerenderEnvironment = isRunnableDevEnvironment ( prerenderEnvironment )
64+ ? ( prerenderEnvironment as RunnableDevEnvironment )
65+ : undefined ;
66+
5467 // TODO: let this handle non-runnable environments that don't intercept requests
55- if ( ! isRunnableDevEnvironment ( viteServer . environments [ ASTRO_VITE_ENVIRONMENT_NAMES . ssr ] ) ) {
68+ if ( ! runnableSsrEnvironment && ! runnablePrerenderEnvironment ) {
5669 return ;
5770 }
58- const environment = viteServer . environments [
59- ASTRO_VITE_ENVIRONMENT_NAMES . ssr
60- ] as RunnableDevEnvironment ;
61- const loader = createViteLoader ( viteServer , environment ) ;
62- const { default : createAstroServerApp } =
63- await environment . runner . import <
64- typeof import ( '../vite-plugin-app/createAstroServerApp.js' )
65- > ( ASTRO_DEV_SERVER_APP_ID ) ;
66- const controller = createController ( { loader } ) ;
67- const { handler } = await createAstroServerApp ( controller , settings , loader , logger ) ;
68- const { manifest } = await environment . runner . import < {
69- manifest : SSRManifest ;
70- } > ( SERIALIZED_MANIFEST_ID ) ;
71+
72+ async function createHandler ( environment : RunnableDevEnvironment ) {
73+ const loader = createViteLoader ( viteServer , environment ) ;
74+ const { default : createAstroServerApp } =
75+ await environment . runner . import <
76+ typeof import ( '../vite-plugin-app/createAstroServerApp.js' )
77+ > ( ASTRO_DEV_SERVER_APP_ID ) ;
78+ const controller = createController ( { loader } ) ;
79+ const { handler } = await createAstroServerApp ( controller , settings , loader , logger ) ;
80+ const { manifest } = await environment . runner . import < {
81+ manifest : SSRManifest ;
82+ } > ( SERIALIZED_MANIFEST_ID ) ;
83+ return { controller, handler, loader, manifest, environment } ;
84+ }
85+
86+ const ssrHandler = runnableSsrEnvironment
87+ ? await createHandler ( runnableSsrEnvironment )
88+ : undefined ;
89+ const prerenderHandler = runnablePrerenderEnvironment
90+ ? await createHandler ( runnablePrerenderEnvironment )
91+ : undefined ;
7192 const localStorage = new AsyncLocalStorage ( ) ;
7293
7394 function handleUnhandledRejection ( rejection : any ) {
@@ -78,14 +99,25 @@ export default function createVitePluginAstroServer({
7899 message : AstroErrorData . UnhandledRejection . message ( rejection ?. stack || rejection ) ,
79100 } ) ;
80101 const store = localStorage . getStore ( ) ;
81- if ( store instanceof IncomingMessage ) {
82- setRouteError ( controller . state , store . url ! , error ) ;
102+ const handlers = [ ] ;
103+ if ( ssrHandler ) handlers . push ( ssrHandler ) ;
104+ if ( prerenderHandler ) handlers . push ( prerenderHandler ) ;
105+ for ( const currentHandler of handlers ) {
106+ if ( store instanceof IncomingMessage ) {
107+ setRouteError ( currentHandler . controller . state , store . url ! , error ) ;
108+ }
109+ const { errorWithMetadata } = recordServerError (
110+ currentHandler . loader ,
111+ currentHandler . manifest ,
112+ logger ,
113+ error ,
114+ ) ;
115+ setTimeout (
116+ async ( ) =>
117+ currentHandler . loader . webSocketSend ( await getViteErrorPayload ( errorWithMetadata ) ) ,
118+ 200 ,
119+ ) ;
83120 }
84- const { errorWithMetadata } = recordServerError ( loader , manifest , logger , error ) ;
85- setTimeout (
86- async ( ) => loader . webSocketSend ( await getViteErrorPayload ( errorWithMetadata ) ) ,
87- 200 ,
88- ) ;
89121 }
90122
91123 process . on ( 'unhandledRejection' , handleUnhandledRejection ) ;
@@ -94,6 +126,14 @@ export default function createVitePluginAstroServer({
94126 } ) ;
95127
96128 return ( ) => {
129+ const shouldHandlePrerenderInCore = Boolean (
130+ ( viteServer as any ) [ devPrerenderMiddlewareSymbol ] ,
131+ ) ;
132+
133+ if ( ! ssrHandler && ! ( prerenderHandler && shouldHandlePrerenderInCore ) ) {
134+ return ;
135+ }
136+
97137 // Push this middleware to the front of the stack so that it can intercept responses.
98138 // fix(#6067): always inject this to ensure zombie base handling is killed after restarts
99139 viteServer . middlewares . stack . unshift ( {
@@ -115,18 +155,58 @@ export default function createVitePluginAstroServer({
115155 handle : secFetchMiddleware ( logger , settings . config . security ?. allowedDomains ) ,
116156 } ) ;
117157
118- // Note that this function has a name so other middleware can find it.
119- viteServer . middlewares . use ( async function astroDevHandler ( request , response ) {
120- if ( request . url === undefined || ! request . method ) {
121- response . writeHead ( 500 , 'Incomplete request' ) ;
122- response . end ( ) ;
123- return ;
124- }
158+ if ( prerenderHandler && shouldHandlePrerenderInCore ) {
159+ viteServer . middlewares . use (
160+ async function astroDevPrerenderHandler ( request , response , next ) {
161+ if ( request . url === undefined || ! request . method ) {
162+ response . writeHead ( 500 , 'Incomplete request' ) ;
163+ response . end ( ) ;
164+ return ;
165+ }
166+
167+ if ( request . url . startsWith ( '/@' ) || request . url . startsWith ( '/__' ) ) {
168+ return next ( ) ;
169+ }
170+
171+ if ( request . url . includes ( '/node_modules/' ) ) {
172+ return next ( ) ;
173+ }
125174
126- localStorage . run ( request , ( ) => {
127- handler ( request , response ) ;
175+ try {
176+ const pathname = decodeURI ( new URL ( request . url , 'http://localhost' ) . pathname ) ;
177+ const { routes } =
178+ await prerenderHandler . environment . runner . import ( 'virtual:astro:routes' ) ;
179+ const routesList = { routes : routes . map ( ( r : any ) => r . routeData ) } ;
180+ const matches = matchAllRoutes ( pathname , routesList ) ;
181+
182+ if ( ! matches . some ( ( route ) => route . prerender ) ) {
183+ return next ( ) ;
184+ }
185+
186+ localStorage . run ( request , ( ) => {
187+ prerenderHandler . handler ( request , response ) ;
188+ } ) ;
189+ } catch ( err ) {
190+ next ( err ) ;
191+ }
192+ } ,
193+ ) ;
194+ }
195+
196+ if ( ssrHandler ) {
197+ // Note that this function has a name so other middleware can find it.
198+ viteServer . middlewares . use ( async function astroDevHandler ( request , response ) {
199+ if ( request . url === undefined || ! request . method ) {
200+ response . writeHead ( 500 , 'Incomplete request' ) ;
201+ response . end ( ) ;
202+ return ;
203+ }
204+
205+ localStorage . run ( request , ( ) => {
206+ ssrHandler . handler ( request , response ) ;
207+ } ) ;
128208 } ) ;
129- } ) ;
209+ }
130210 } ;
131211 } ,
132212 } ;
0 commit comments