1- import {
2- OUTPUT_BUNDLE_BROWSER_DIR ,
3- OUTPUT_BUNDLE_SERVER_DIR ,
4- PUBLIC_USER_DIR ,
5- SERVER_MANIFEST_OUTPUT_PATH ,
6- SITE_MANIFEST_OUTPUT_PATH ,
7- } from "@/build/constants.js" ;
8- import { filePathToRoutingPath } from "@/build/filepath-to-routing-path.js" ;
9- import { generate_html_template } from "@/build/generate_html_template.js" ;
1+ import { SERVER_MANIFEST_OUTPUT_PATH } from "@/build/constants.js" ;
2+ import { defineServeStaticHandler } from "@/runtime/define-serve-static.js" ;
3+ import { define_ssr_handlers } from "@/runtime/define-ssr-handlers.js" ;
104import { logger } from "@/utils/logger.js" ;
115import { measureTime } from "@/utils/time-perf.js" ;
126import fse from "fs-extra" ;
13- import {
14- defineHandler ,
15- type EventHandlerRequest ,
16- H3 ,
17- type H3Event ,
18- html ,
19- serve ,
20- serveStatic ,
21- } from "h3" ;
7+ import { H3 , serve } from "h3" ;
228import kleur from "kleur" ;
23- import { readFile , stat } from "node:fs/promises" ;
24- import { extname , join , resolve } from "pathe" ;
25- import { Fragment , h } from "preact" ;
26- import { renderToStringAsync } from "preact-render-to-string" ;
27- import type { HYDRATE_DATA , PageModule , SERVER_MANIFEST , ServerEntryModule } from "types/index.js" ;
9+ import type { SERVER_MANIFEST } from "types/index.js" ;
2810
2911export async function start ( ) {
3012 measureTime ( "pranx-start" ) ;
@@ -37,116 +19,13 @@ export async function start() {
3719
3820 const app = new H3 ( ) ;
3921
40- await attach_server_side_pages_to_app ( server_manifest , app ) ;
22+ await define_ssr_handlers ( server_manifest , app ) ;
4123
42- app . on ( "GET" , "**" , ( event ) => createServeStatic ( event ) ) ;
24+ app . on ( "GET" , "**" , ( event ) => defineServeStaticHandler ( event ) ) ;
4325
44- const SERVER = serve ( app , { port : PORT } ) ;
26+ const server_instance = serve ( app , { port : PORT } ) ;
4527
46- await SERVER . ready ( ) ;
28+ await server_instance . ready ( ) ;
4729
48- const START_TIME = measureTime ( "pranx-start" ) ;
49-
50- logger . success ( `Start in ${ START_TIME } ms` ) ;
30+ logger . success ( `Start in ${ measureTime ( "pranx-start" ) } ms` ) ;
5131}
52-
53- const createServeStatic = ( event : H3Event < EventHandlerRequest > ) =>
54- serveStatic ( event , {
55- indexNames : [ "/index.html" ] ,
56-
57- getContents : async ( id ) => {
58- const target_file = join ( OUTPUT_BUNDLE_BROWSER_DIR , id ) ;
59- const target_public_file = join ( PUBLIC_USER_DIR , id ) ;
60-
61- const existsTargetFile = await fse . exists ( target_file ) ;
62-
63- const buffer = await readFile ( existsTargetFile ? target_file : target_public_file ) ;
64-
65- return new Uint8Array ( buffer ) ;
66- } ,
67-
68- getMeta : async ( id ) => {
69- const target_file = join ( OUTPUT_BUNDLE_BROWSER_DIR , id ) ;
70- const target_public_file = join ( PUBLIC_USER_DIR , id ) ;
71-
72- const existsTargetFile = await fse . exists ( target_file ) ;
73-
74- const stats = await stat ( existsTargetFile ? target_file : target_public_file ) . catch ( ( ) => { } ) ;
75-
76- if ( stats ?. isFile ( ) ) {
77- return stats ;
78- }
79-
80- return undefined ;
81- } ,
82-
83- headers : {
84- "Cache-Control" : "public, max-age=2592000, immutable" , // agresive caching
85- "Expires" : new Date ( Date . now ( ) + 2592000000 ) . toUTCString ( ) , // one month
86- } ,
87- } ) ;
88-
89- const attach_server_side_pages_to_app = async ( server_manifest : SERVER_MANIFEST , app : H3 ) => {
90- for ( const route of server_manifest . routes ) {
91- if ( route . rendering_kind === "server-side" ) {
92- let server_entry_module : ServerEntryModule | null = null ;
93- server_entry_module = ( await import ( server_manifest . entry_server ) ) as ServerEntryModule ;
94-
95- const file_absolute = resolve ( join ( OUTPUT_BUNDLE_SERVER_DIR , "pages" , route . module ) ) ;
96- const { default : page , getServerSideProps } = ( await import ( file_absolute ) ) as PageModule ;
97-
98- const hydrate_data = ( await fse . readJSON ( SITE_MANIFEST_OUTPUT_PATH ) ) as HYDRATE_DATA ;
99- const url_for_routing_match = filePathToRoutingPath ( route . path , false ) ;
100-
101- app . on (
102- "GET" ,
103- url_for_routing_match ,
104- defineHandler ( async ( event ) => {
105- // For files that match with dynamic routes
106- if ( extname ( event . url . pathname . split ( "/" ) . at ( - 1 ) || "" ) ) {
107- return createServeStatic ( event ) ;
108- }
109-
110- let props_to_return = { } ;
111-
112- if ( getServerSideProps ) {
113- props_to_return = await getServerSideProps ( {
114- event,
115- } ) ;
116- }
117-
118- event . res . headers . set ( "Cache-Control" , "private, no-cache, no-store, must-revalidate" ) ;
119-
120- if ( event . url . searchParams . get ( "props" ) === "only" ) {
121- return {
122- props : props_to_return ,
123- } ;
124- }
125-
126- const target_route_index = hydrate_data . routes . findIndex ( ( r ) => r . path === route . path ) ;
127-
128- if ( target_route_index === - 1 || ! hydrate_data . routes [ target_route_index ] ) {
129- logger . error ( `Route not found in hydrate data: ${ route . path } ` ) ;
130- event . res . status = 500 ;
131- return html ( event , "Internal Server Error" ) ;
132- }
133-
134- hydrate_data . routes [ target_route_index ] . props = props_to_return ;
135-
136- const page_prerendered = await renderToStringAsync (
137- h ( server_entry_module ?. default || Fragment , { } , h ( page , props_to_return , null ) )
138- ) ;
139-
140- const html_string = generate_html_template ( {
141- page_prerendered,
142- hydrate_data_as_string : JSON . stringify ( hydrate_data ) ,
143- minify : true ,
144- css : route . css ,
145- } ) ;
146-
147- return html ( event , html_string ) ;
148- } )
149- ) ;
150- }
151- }
152- } ;
0 commit comments