@@ -14,10 +14,7 @@ import cssPlugin, { cssLoader, isCSS } from '../plugins/css.ts'
14
14
import { ensureTextFile , existsDir , existsFile , lazyRemove } from '../shared/fs.ts'
15
15
import log , { Measure } from '../shared/log.ts'
16
16
import util from '../shared/util.ts'
17
- import type {
18
- Aleph as IAleph , ImportMap , LoadInput , LoadOutput , RouterURL , ResolveResult ,
19
- TransformOutput , TransformInput
20
- } from '../types.ts'
17
+ import type { Aleph as IAleph , ImportMap , LoadInput , LoadOutput , RouterURL , ResolveResult , TransformOutput , TransformInput } from '../types.ts'
21
18
import { VERSION } from '../version.ts'
22
19
import { Analyzer } from './analyzer.ts'
23
20
import { cache } from './cache.ts'
@@ -29,7 +26,7 @@ import {
29
26
} from './helper.ts'
30
27
import { getContentType } from './mime.ts'
31
28
import type { SSRData } from './renderer.ts'
32
- import { Renderer } from './renderer.ts'
29
+ import { createHtml , Renderer } from './renderer.ts'
33
30
34
31
/** A module includes the compilation details. */
35
32
export type Module = {
@@ -470,7 +467,7 @@ export class Aleph implements IAleph {
470
467
return null
471
468
}
472
469
473
- /** get api route by given location. */
470
+ /** get api route by the given location. */
474
471
async getAPIRoute ( location : { pathname : string , search ?: string } ) : Promise < [ RouterURL , Module ] | null > {
475
472
const router = this . #apiRouting. createRouter ( location )
476
473
if ( router !== null ) {
@@ -539,7 +536,7 @@ export class Aleph implements IAleph {
539
536
this . #dists. add ( pathname )
540
537
}
541
538
542
- /** get ssr data */
539
+ /** get ssr data by the given location(page), return `null` if no data defined */
543
540
async getSSRData ( loc : { pathname : string , search ?: string } ) : Promise < Record < string , SSRData > | null > {
544
541
const [ router , nestedModules ] = this . #pageRouting. createRouter ( loc )
545
542
const { routePath } = router
@@ -591,34 +588,34 @@ export class Aleph implements IAleph {
591
588
return data
592
589
}
593
590
594
- /** get page ssr html */
595
- async getPageHTML ( loc : { pathname : string , search ?: string } ) : Promise < [ number , string ] > {
591
+ /** render page to HTML by the given location */
592
+ async renderPage ( loc : { pathname : string , search ?: string } ) : Promise < [ number , string ] > {
596
593
const [ router , nestedModules ] = this . #pageRouting. createRouter ( loc )
597
594
const { routePath } = router
598
595
const path = loc . pathname + ( loc . search || '' )
599
596
600
597
if ( ! this . isSSRable ( loc . pathname ) ) {
601
598
const [ html ] = await this . #renderer. cache ( '-' , 'spa-index' , async ( ) => {
602
- return [ await this . #renderer . renderSPAIndexPage ( ) , null ]
599
+ return [ this . createSPAIndexHtml ( ) , null ]
603
600
} )
604
601
return [ 200 , html ]
605
602
}
606
603
607
604
if ( routePath === '' ) {
608
605
const [ html ] = await this . #renderer. cache ( '404' , path , async ( ) => {
609
606
const [ _ , nestedModules ] = this . #pageRouting. createRouter ( { pathname : '/404' } )
610
- return await this . renderPage ( router , nestedModules . slice ( 0 , 1 ) )
607
+ return await this . # renderPage( router , nestedModules . slice ( 0 , 1 ) )
611
608
} )
612
609
return [ 404 , html ]
613
610
}
614
611
615
612
const [ html ] = await this . #renderer. cache ( routePath , path , async ( ) => {
616
- return await this . renderPage ( router , nestedModules )
613
+ return await this . # renderPage( router , nestedModules )
617
614
} )
618
615
return [ 200 , html ]
619
616
}
620
617
621
- private async renderPage ( url : RouterURL , nestedModules : string [ ] ) : Promise < [ string , Record < string , SSRData > | null ] > {
618
+ async # renderPage( url : RouterURL , nestedModules : string [ ] ) : Promise < [ string , Record < string , SSRData > | null ] > {
622
619
const href = url . toString ( )
623
620
let [ html , data ] = await this . #renderer. renderPage ( url , nestedModules )
624
621
for ( const callback of this . #ssrListeners) {
@@ -682,11 +679,24 @@ export class Aleph implements IAleph {
682
679
return code
683
680
}
684
681
685
- /** get ssr html scripts */
686
- getSSRHTMLScripts ( entryFile ?: string ) {
682
+ /** create the index html for SPA mode. */
683
+ private createSPAIndexHtml ( ) : string {
684
+ // todo: render custom fallback page
685
+ return createHtml ( {
686
+ lang : this . config . i18n . defaultLocale ,
687
+ head : [ ] ,
688
+ scripts : this . getScripts ( ) ,
689
+ body : '<div id="__aleph"></div>' ,
690
+ minify : ! this . isDev
691
+ } )
692
+ }
693
+
694
+ /** get scripts for html output */
695
+ getScripts ( entryFile ?: string ) {
687
696
const { framework } = this . config
688
697
const basePath = util . trimSuffix ( this . config . basePath , '/' )
689
698
const alephPkgPath = getAlephPkgUri ( ) . replace ( 'https://' , '' ) . replace ( 'http://localhost:' , 'http_localhost_' )
699
+ const syncChunks = this . #bundler. getSyncChunks ( )
690
700
691
701
if ( this . isDev ) {
692
702
const preload : string [ ] = [
@@ -715,7 +725,7 @@ export class Aleph implements IAleph {
715
725
716
726
return [
717
727
simpleJSMinify ( bundlerRuntimeCode ) ,
718
- ... this . #bundler . getSyncChunks ( ) . map ( filename => ( {
728
+ ...syncChunks . map ( filename => ( {
719
729
src : `${ basePath } /_aleph/${ filename } `
720
730
} ) )
721
731
]
@@ -739,7 +749,7 @@ export class Aleph implements IAleph {
739
749
}
740
750
741
751
/** common compiler options */
742
- get commonCompileOptions ( ) : TransformOptions {
752
+ get commonCompilerOptions ( ) : TransformOptions {
743
753
return {
744
754
workingDir : this . workingDir ,
745
755
alephPkgUri : getAlephPkgUri ( ) ,
@@ -895,7 +905,7 @@ export class Aleph implements IAleph {
895
905
return await import ( `file://${ join ( this . buildDir , jsFile ) } #${ ( hash || sourceHash ) . slice ( 0 , 6 ) } ` )
896
906
}
897
907
898
- async readModuleJS ( module : Module , injectHMRCode = false ) : Promise < Uint8Array | null > {
908
+ async getModuleJS ( module : Module , injectHMRCode = false ) : Promise < Uint8Array | null > {
899
909
const { specifier, jsFile, jsBuffer } = module
900
910
if ( ! jsBuffer ) {
901
911
const cacheFp = join ( this . buildDir , jsFile )
@@ -918,6 +928,7 @@ export class Aleph implements IAleph {
918
928
if ( 'csrCode' in module ) {
919
929
code = ( module as any ) . csrCode
920
930
} else {
931
+ [ code ] = util . splitBy ( code , '\n//# sourceMappingURL=' , true )
921
932
const { code : csrCode } = await stripSsrCode ( specifier , code , { sourceMap : true , swcOptions : { sourceType : SourceType . JS } } )
922
933
// cache csr code
923
934
Object . assign ( module , { csrCode } )
@@ -1134,7 +1145,7 @@ export class Aleph implements IAleph {
1134
1145
const ms = new Measure ( )
1135
1146
const encoder = new TextEncoder ( )
1136
1147
const { code, deps, denoHooks, ssrPropsFn, ssgPathsFn, starExports, map } = await transform ( specifier , source . code , {
1137
- ...this . commonCompileOptions ,
1148
+ ...this . commonCompilerOptions ,
1138
1149
sourceMap : this . isDev ,
1139
1150
swcOptions : {
1140
1151
sourceType : source . type
@@ -1246,12 +1257,7 @@ export class Aleph implements IAleph {
1246
1257
1247
1258
if ( module . deps . length > 0 ) {
1248
1259
let fsync = false
1249
- const encoder = new TextEncoder ( )
1250
1260
const hasher = createHash ( 'md5' ) . update ( module . sourceHash )
1251
- // preload js buffer
1252
- if ( module . deps . findIndex ( dep => dep . hashLoc !== undefined ) >= 0 ) {
1253
- await this . readModuleJS ( module )
1254
- }
1255
1261
await Promise . all ( module . deps . map ( async ( { specifier, hashLoc } ) => {
1256
1262
let depModule : Module | null
1257
1263
if ( ignoreDeps ) {
@@ -1277,7 +1283,7 @@ export class Aleph implements IAleph {
1277
1283
} ) )
1278
1284
module . hash = hasher . toString ( )
1279
1285
if ( fsync ) {
1280
- await this . writeModule ( module )
1286
+ await this . cacheModule ( module )
1281
1287
}
1282
1288
} else {
1283
1289
module . hash = module . sourceHash
@@ -1315,7 +1321,7 @@ export class Aleph implements IAleph {
1315
1321
mod . hash = hasher . toString ( )
1316
1322
callback ( mod )
1317
1323
this . applyCompilationSideEffect ( mod , callback )
1318
- this . writeModule ( mod )
1324
+ this . cacheModule ( mod )
1319
1325
}
1320
1326
}
1321
1327
}
@@ -1324,9 +1330,9 @@ export class Aleph implements IAleph {
1324
1330
/** replace dep hash in the `jsBuffer` and remove `csrCode` cache if it exits */
1325
1331
private async replaceDepHash ( module : Module , hashLoc : number , hash : string ) {
1326
1332
const hashData = ( new TextEncoder ( ) ) . encode ( hash . substr ( 0 , 6 ) )
1327
- await this . readModuleJS ( module )
1328
- if ( module . jsBuffer && ! equals ( hashData , module . jsBuffer . slice ( hashLoc , hashLoc + 6 ) ) ) {
1329
- copy ( hashData , module . jsBuffer , hashLoc )
1333
+ const jsBuffer = await this . getModuleJS ( module )
1334
+ if ( jsBuffer && ! equals ( hashData , jsBuffer . slice ( hashLoc , hashLoc + 6 ) ) ) {
1335
+ copy ( hashData , jsBuffer , hashLoc )
1330
1336
if ( 'csrCode' in module ) {
1331
1337
Reflect . deleteProperty ( module , 'csrCode' )
1332
1338
}
@@ -1344,7 +1350,7 @@ export class Aleph implements IAleph {
1344
1350
}
1345
1351
}
1346
1352
1347
- private async writeModule ( module : Module ) {
1353
+ private async cacheModule ( module : Module ) {
1348
1354
const { specifier, jsBuffer, jsFile } = module
1349
1355
if ( jsBuffer ) {
1350
1356
const cacheFp = join ( this . buildDir , jsFile )
@@ -1378,9 +1384,10 @@ export class Aleph implements IAleph {
1378
1384
const outputDir = join ( this . workingDir , this . config . build . outputDir )
1379
1385
1380
1386
if ( ssr === false ) {
1381
- const html = await this . #renderer . renderSPAIndexPage ( )
1387
+ const html = this . createSPAIndexHtml ( )
1382
1388
await ensureTextFile ( join ( outputDir , 'index.html' ) , html )
1383
1389
await ensureTextFile ( join ( outputDir , '404.html' ) , html )
1390
+ // todo: 500 page
1384
1391
return
1385
1392
}
1386
1393
@@ -1422,7 +1429,7 @@ export class Aleph implements IAleph {
1422
1429
const [ router , nestedModules ] = this . #pageRouting. createRouter ( { pathname, search } )
1423
1430
if ( router . routePath !== '' ) {
1424
1431
const href = router . toString ( )
1425
- const [ html , data ] = await this . renderPage ( router , nestedModules )
1432
+ const [ html , data ] = await this . # renderPage( router , nestedModules )
1426
1433
await ensureTextFile ( join ( outputDir , pathname , 'index.html' + ( search || '' ) ) , html )
1427
1434
if ( data ) {
1428
1435
const dataFile = join (
@@ -1442,7 +1449,7 @@ export class Aleph implements IAleph {
1442
1449
if ( nestedModules . length > 0 ) {
1443
1450
await this . compile ( nestedModules [ 0 ] )
1444
1451
}
1445
- const [ html ] = await this . renderPage ( router , nestedModules . slice ( 0 , 1 ) )
1452
+ const [ html ] = await this . # renderPage( router , nestedModules . slice ( 0 , 1 ) )
1446
1453
await ensureTextFile ( join ( outputDir , '404.html' ) , html )
1447
1454
}
1448
1455
}
0 commit comments