@@ -54,7 +54,7 @@ export default class Project {
54
54
baseUrl : '/' ,
55
55
defaultLocale : 'en' ,
56
56
ssr : {
57
- fallback : 'fallback .html'
57
+ fallback : '404 .html'
58
58
} ,
59
59
buildTarget : mode === 'development' ? 'es2018' : 'es2015' ,
60
60
sourceMap : false ,
@@ -89,10 +89,15 @@ export default class Project {
89
89
}
90
90
91
91
isHMRable ( moduleId : string ) {
92
- if ( reHttp . test ( moduleId ) ) {
93
- return false
94
- }
95
- return moduleId === './app.js' || moduleId === './data.js' || ( moduleId === './data/index.js' && ! this . #modules. has ( './data.js' ) ) || moduleId . startsWith ( './pages/' ) || moduleId . startsWith ( './components/' ) || reStyleModuleExt . test ( moduleId )
92
+ return ! reHttp . test ( moduleId ) && (
93
+ moduleId === './404.js' ||
94
+ moduleId === './app.js' ||
95
+ moduleId === './data.js' ||
96
+ ( moduleId === './data/index.js' && ! this . #modules. has ( './data.js' ) ) ||
97
+ moduleId . startsWith ( './pages/' ) ||
98
+ moduleId . startsWith ( './components/' ) ||
99
+ reStyleModuleExt . test ( moduleId )
100
+ )
96
101
}
97
102
98
103
getModule ( id : string ) : Module | null {
@@ -168,10 +173,13 @@ export default class Project {
168
173
Array . from ( this . #pageModules. keys ( ) ) ,
169
174
{
170
175
location,
171
- defaultLocale,
172
- fallback : '/404'
176
+ defaultLocale
173
177
}
174
178
)
179
+ if ( url . pagePath === '' ) {
180
+ return [ 200 , this . getSPAIndexHtml ( ) ]
181
+ }
182
+
175
183
const mainModule = this . #modules. get ( './main.js' ) !
176
184
const { code, head, body } = await this . _renderPage ( url )
177
185
const html = createHtml ( {
@@ -278,13 +286,13 @@ export default class Project {
278
286
279
287
const { ssr } = this . config
280
288
if ( ssr ) {
281
- const fallback = ( ( util . isPlainObject ( ssr ) && ssr . fallback ? util . trimSuffix ( ssr . fallback , '.html' ) : '' ) || 'fallback' ) + '.html'
282
- await writeTextFile ( path . join ( outputDir , fallback ) , this . getSPAIndexHtml ( ) )
283
289
for ( const pathname of this . #pageModules. keys ( ) ) {
284
290
const [ _ , html ] = await this . getPageHtml ( { pathname } )
285
291
const htmlFile = path . join ( outputDir , pathname , 'index.html' )
286
292
await writeTextFile ( htmlFile , html )
287
293
}
294
+ const fallback = path . join ( outputDir , util . isPlainObject ( ssr ) && ssr . fallback ? ssr . fallback : '404.html' )
295
+ await writeTextFile ( fallback , this . getSPAIndexHtml ( ) )
288
296
} else {
289
297
await writeTextFile ( path . join ( outputDir , 'index.html' ) , this . getSPAIndexHtml ( ) )
290
298
}
@@ -340,9 +348,10 @@ export default class Project {
340
348
if ( typeof ssr === 'boolean' ) {
341
349
Object . assign ( this . config , { ssr } )
342
350
} else if ( util . isPlainObject ( ssr ) ) {
351
+ const fallback = util . isNEString ( ssr . fallback ) ? ssr . fallback : '404.html'
343
352
const include = util . isArray ( ssr . include ) ? ssr . include : [ ]
344
353
const exclude = util . isArray ( ssr . exclude ) ? ssr . exclude : [ ]
345
- Object . assign ( this . config , { ssr : { include, exclude } } )
354
+ Object . assign ( this . config , { ssr : { fallback , include, exclude } } )
346
355
}
347
356
if ( / ^ e s ( 2 0 \d { 2 } | n e x t ) $ / i. test ( buildTarget ) ) {
348
357
Object . assign ( this . config , { buildTarget : buildTarget . toLowerCase ( ) } )
@@ -394,6 +403,7 @@ export default class Project {
394
403
switch ( name . replace ( reModuleExt , '' ) ) {
395
404
case 'app' :
396
405
case 'data' :
406
+ case '404' :
397
407
await this . _compile ( './' + name )
398
408
break
399
409
}
@@ -453,6 +463,7 @@ export default class Project {
453
463
}
454
464
const moduleId = './' + path . replace ( reModuleExt , '.js' )
455
465
switch ( moduleId ) {
466
+ case './404.js' :
456
467
case './app.js' :
457
468
case './data.js' :
458
469
case './data/index.js' : {
@@ -558,6 +569,7 @@ export default class Project {
558
569
locales : { } ,
559
570
dataModule : null ,
560
571
appModule : null ,
572
+ e404Module : null ,
561
573
pageModules : { }
562
574
}
563
575
const module = this . _parseUrl ( './main.js' )
@@ -585,6 +597,14 @@ export default class Project {
585
597
}
586
598
deps . push ( { url, hash } )
587
599
}
600
+ if ( this . #modules. has ( './404.js' ) ) {
601
+ const { url, hash } = this . #modules. get ( './404.js' ) !
602
+ config . e404Module = {
603
+ moduleId : './404.js' ,
604
+ hash
605
+ }
606
+ deps . push ( { url, hash } )
607
+ }
588
608
this . #pageModules. forEach ( ( { moduleId } , pagePath ) => {
589
609
const { url, hash } = this . #modules. get ( moduleId ) !
590
610
const mod = { moduleId, hash }
@@ -791,7 +811,7 @@ export default class Project {
791
811
const compileOptions = {
792
812
target : this . config . buildTarget ,
793
813
mode : this . mode ,
794
- reactRefresh : this . isDev && ! mod . isRemote && ( mod . id === './app.js' || mod . id . startsWith ( './pages/' ) || mod . id . startsWith ( './components/' ) ) ,
814
+ reactRefresh : this . isDev && ! mod . isRemote && ( mod . id === './404.js' || mod . id === './ app.js' || mod . id . startsWith ( './pages/' ) || mod . id . startsWith ( './components/' ) ) ,
795
815
rewriteImportPath : ( path : string ) => this . _rewriteImportPath ( mod , path ) ,
796
816
}
797
817
const { diagnostics, outputText, sourceMapText } = compile ( mod . url , sourceContent , compileOptions )
@@ -977,46 +997,40 @@ export default class Project {
977
997
978
998
private async _renderPage ( url : RouterURL ) {
979
999
const start = performance . now ( )
980
- const ret : RenderResult = { code : 200 , head : [ ] , body : '' }
981
- if ( this . #pageModules. has ( url . pagePath ) ) {
982
- const pm = this . #pageModules. get ( url . pagePath ) !
983
- if ( pm . rendered . has ( url . pathname ) ) {
984
- const cache = pm . rendered . get ( url . pathname ) !
985
- return { ...cache }
986
- }
987
- try {
988
- const appModule = this . #modules. get ( './app.js' )
989
- const pageModule = this . #modules. get ( pm . moduleId ) !
990
- const [
991
- { renderPage, renderHead } ,
992
- app ,
993
- page
994
- ] = await Promise . all ( [
995
- import ( this . #modules. get ( '//deno.land/x/aleph/renderer.js' ) ! . jsFile ) ,
996
- appModule ? this . importModuleAsComponent ( './app.js' ) : Promise . resolve ( { } ) ,
997
- this . importModuleAsComponent ( pm . moduleId )
998
- ] )
999
- const data = await this . getData ( )
1000
- const html = renderPage ( data , url , appModule ? app : undefined , page )
1001
- const head = renderHead ( [
1002
- pageModule . deps . map ( ( { url } ) => url ) . filter ( url => reStyleModuleExt . test ( url ) ) ,
1003
- appModule ?. deps . map ( ( { url } ) => url ) . filter ( url => reStyleModuleExt . test ( url ) )
1004
- ] . filter ( Boolean ) . flat ( ) )
1005
- ret . code = 200
1006
- ret . head = head
1007
- ret . body = `<main>${ html } </main>`
1008
- pm . rendered . set ( url . pathname , { ...ret } )
1009
- log . debug ( `render page '${ url . pagePath } ' in ${ Math . round ( performance . now ( ) - start ) } ms` )
1010
- } catch ( err ) {
1011
- ret . code = 500
1012
- ret . head = [ '<title>500 Error - Aleph.js</title>' ]
1013
- ret . body = `<pre>${ AnsiUp . ansi_to_html ( err . stack ) } </pre>`
1014
- log . error ( err . stack )
1015
- }
1016
- } else {
1017
- ret . code = 404
1018
- ret . head = [ '<title ssr>404 Error - Aleph.js</title>' ]
1019
- ret . body = '<main><p><strong><code>404</code></strong><small> - </small><span>page not found</span></p></main>'
1000
+ const ret : RenderResult = { code : 200 , head : [ ] , body : '<main></main>' }
1001
+ const pm = this . #pageModules. get ( url . pagePath ) !
1002
+ if ( pm . rendered . has ( url . pathname ) ) {
1003
+ const cache = pm . rendered . get ( url . pathname ) !
1004
+ return { ...cache }
1005
+ }
1006
+ try {
1007
+ const appModule = this . #modules. get ( './app.js' )
1008
+ const pageModule = this . #modules. get ( pm . moduleId ) !
1009
+ const [
1010
+ { renderPage, renderHead } ,
1011
+ app ,
1012
+ page
1013
+ ] = await Promise . all ( [
1014
+ import ( this . #modules. get ( '//deno.land/x/aleph/renderer.js' ) ! . jsFile ) ,
1015
+ appModule ? this . importModuleAsComponent ( './app.js' ) : Promise . resolve ( { } ) ,
1016
+ this . importModuleAsComponent ( pm . moduleId )
1017
+ ] )
1018
+ const data = await this . getData ( )
1019
+ const html = renderPage ( data , url , appModule ? app : undefined , page )
1020
+ const head = renderHead ( [
1021
+ pageModule . deps . map ( ( { url } ) => url ) . filter ( url => reStyleModuleExt . test ( url ) ) ,
1022
+ appModule ?. deps . map ( ( { url } ) => url ) . filter ( url => reStyleModuleExt . test ( url ) )
1023
+ ] . filter ( Boolean ) . flat ( ) )
1024
+ ret . code = 200
1025
+ ret . head = head
1026
+ ret . body = `<main>${ html } </main>`
1027
+ pm . rendered . set ( url . pathname , { ...ret } )
1028
+ log . debug ( `render page '${ url . pagePath } ' in ${ Math . round ( performance . now ( ) - start ) } ms` )
1029
+ } catch ( err ) {
1030
+ ret . code = 500
1031
+ ret . head = [ '<title>500 Error - Aleph.js</title>' ]
1032
+ ret . body = `<main><pre>${ AnsiUp . ansi_to_html ( err . stack ) } </pre></main>`
1033
+ log . error ( err . stack )
1020
1034
}
1021
1035
return ret
1022
1036
}
0 commit comments