9
9
OriginRequestDefaultHandlerManifest ,
10
10
OriginRequestApiHandlerManifest ,
11
11
RoutesManifest ,
12
- OriginRequestImageHandlerManifest
12
+ OriginRequestImageHandlerManifest ,
13
+ DynamicPageKeyValue
13
14
} from "./types" ;
14
15
import { isDynamicRoute , isOptionalCatchAllRoute } from "./lib/isDynamicRoute" ;
15
16
import pathToPosix from "./lib/pathToPosix" ;
@@ -23,7 +24,7 @@ import createServerlessConfig from "./lib/createServerlessConfig";
23
24
import { isTrailingSlashRedirect } from "./routing/redirector" ;
24
25
import readDirectoryFiles from "./lib/readDirectoryFiles" ;
25
26
import filterOutDirectories from "./lib/filterOutDirectories" ;
26
- import { PrerenderManifest } from "next/dist/build" ;
27
+ import { DynamicSsgRoute , PrerenderManifest , SsgRoute } from "next/dist/build" ;
27
28
import { Item } from "klaw" ;
28
29
import { Job } from "@vercel/nft/out/node-file-trace" ;
29
30
@@ -456,7 +457,10 @@ class Builder {
456
457
] ) ;
457
458
}
458
459
459
- async prepareBuildManifests ( ) : Promise < {
460
+ async prepareBuildManifests (
461
+ routesManifest : RoutesManifest ,
462
+ prerenderManifest : PrerenderManifest
463
+ ) : Promise < {
460
464
defaultBuildManifest : OriginRequestDefaultHandlerManifest ;
461
465
apiBuildManifest : OriginRequestApiHandlerManifest ;
462
466
imageBuildManifest : OriginRequestImageHandlerManifest ;
@@ -487,6 +491,10 @@ class Builder {
487
491
html : {
488
492
dynamic : { } ,
489
493
nonDynamic : { }
494
+ } ,
495
+ ssg : {
496
+ dynamic : { } ,
497
+ nonDynamic : { }
490
498
}
491
499
} ,
492
500
publicFiles : { } ,
@@ -506,6 +514,7 @@ class Builder {
506
514
enableHTTPCompression
507
515
} ;
508
516
517
+ const ssgPages = defaultBuildManifest . pages . ssg ;
509
518
const ssrPages = defaultBuildManifest . pages . ssr ;
510
519
const htmlPages = defaultBuildManifest . pages . html ;
511
520
const apiPages = apiBuildManifest . apis ;
@@ -582,6 +591,144 @@ class Builder {
582
591
}
583
592
} ) ;
584
593
594
+ // Add non-dynamic SSG routes
595
+ Object . entries ( prerenderManifest . routes ) . forEach ( ( [ route , ssgRoute ] ) => {
596
+ // Somehow Next.js generates prerender manifest with default locale prefixed, normalize it
597
+ const defaultLocale = routesManifest . i18n ?. defaultLocale ;
598
+ if ( defaultLocale ) {
599
+ const normalizedRoute = route . replace ( `/${ defaultLocale } /` , "/" ) ;
600
+ ssgRoute . dataRoute = ssgRoute . dataRoute . replace (
601
+ `/${ defaultLocale } /` ,
602
+ "/"
603
+ ) ;
604
+ ssgPages . nonDynamic [ normalizedRoute ] = ssgRoute ;
605
+ } else {
606
+ ssgPages . nonDynamic [ route ] = ssgRoute ;
607
+ }
608
+ } ) ;
609
+
610
+ // Add dynamic SSG routes
611
+ Object . entries ( prerenderManifest . dynamicRoutes ?? { } ) . forEach (
612
+ ( [ route , dynamicSsgRoute ] ) => {
613
+ ssgPages . dynamic [ route ] = dynamicSsgRoute ;
614
+ }
615
+ ) ;
616
+
617
+ // Copy routes for all specified locales
618
+ if ( routesManifest . i18n ) {
619
+ const defaultLocale = routesManifest . i18n . defaultLocale ;
620
+ for ( const locale of routesManifest . i18n . locales ) {
621
+ if ( locale !== defaultLocale ) {
622
+ const localeSsrPages : {
623
+ nonDynamic : {
624
+ [ key : string ] : string ;
625
+ } ;
626
+ dynamic : DynamicPageKeyValue ;
627
+ } = {
628
+ nonDynamic : { } ,
629
+ dynamic : { }
630
+ } ;
631
+
632
+ for ( const key in ssrPages . nonDynamic ) {
633
+ const newKey = key === "/" ? `/${ locale } ` : `/${ locale } ${ key } ` ;
634
+ localeSsrPages . nonDynamic [ newKey ] = ssrPages . nonDynamic [ key ] ;
635
+ }
636
+
637
+ ssrPages . nonDynamic = {
638
+ ...ssrPages . nonDynamic ,
639
+ ...localeSsrPages . nonDynamic
640
+ } ;
641
+
642
+ for ( const key in ssrPages . dynamic ) {
643
+ const newKey = key === "/" ? `/${ locale } ` : `/${ locale } ${ key } ` ;
644
+
645
+ // Initial default value
646
+ localeSsrPages . dynamic [ newKey ] = { file : "" , regex : "" } ;
647
+ const newDynamicSsr = Object . assign (
648
+ localeSsrPages . dynamic [ newKey ] ,
649
+ ssrPages . dynamic [ key ]
650
+ ) ;
651
+
652
+ // Need to update the regex
653
+ newDynamicSsr . regex = pathToRegexStr ( newKey ) ;
654
+ }
655
+
656
+ ssrPages . dynamic = {
657
+ ...ssrPages . dynamic ,
658
+ ...localeSsrPages . dynamic
659
+ } ;
660
+
661
+ const localeSsgPages : {
662
+ dynamic : {
663
+ [ key : string ] : DynamicSsgRoute ;
664
+ } ;
665
+ nonDynamic : {
666
+ [ key : string ] : SsgRoute ;
667
+ } ;
668
+ } = {
669
+ dynamic : { } ,
670
+ nonDynamic : { }
671
+ } ;
672
+
673
+ for ( const key in ssgPages . nonDynamic ) {
674
+ const newKey = key === "/" ? `/${ locale } ` : `/${ locale } ${ key } ` ;
675
+
676
+ // Initial default value
677
+ localeSsgPages . nonDynamic [ newKey ] = {
678
+ initialRevalidateSeconds : false ,
679
+ srcRoute : null ,
680
+ dataRoute : ""
681
+ } ;
682
+
683
+ const newSsgRoute = Object . assign (
684
+ localeSsgPages . nonDynamic [ newKey ] ,
685
+ ssgPages . nonDynamic [ key ]
686
+ ) ;
687
+
688
+ // Replace with localized value
689
+ newSsgRoute . dataRoute = newSsgRoute . dataRoute . replace (
690
+ `/_next/data/${ buildId } /` ,
691
+ `/_next/data/${ buildId } /${ locale } /`
692
+ ) ;
693
+ }
694
+
695
+ ssgPages . nonDynamic = {
696
+ ...ssgPages . nonDynamic ,
697
+ ...localeSsgPages . nonDynamic
698
+ } ;
699
+
700
+ for ( const key in ssgPages . dynamic ) {
701
+ const newKey = key === "/" ? `/${ locale } ` : `/${ locale } ${ key } ` ;
702
+ localeSsgPages . dynamic [ newKey ] = ssgPages . dynamic [ key ] ;
703
+
704
+ const newDynamicSsgRoute = localeSsgPages . dynamic [ newKey ] ;
705
+
706
+ // Replace with localized values
707
+ newDynamicSsgRoute . dataRoute = newDynamicSsgRoute . dataRoute . replace (
708
+ `/_next/data/${ buildId } /` ,
709
+ `/_next/data/${ buildId } /${ locale } /`
710
+ ) ;
711
+ newDynamicSsgRoute . dataRouteRegex = newDynamicSsgRoute . dataRouteRegex . replace (
712
+ `/_next/data/${ buildId } /` ,
713
+ `/_next/data/${ buildId } /${ locale } /`
714
+ ) ;
715
+ newDynamicSsgRoute . fallback =
716
+ typeof newDynamicSsgRoute . fallback === "string"
717
+ ? newDynamicSsgRoute . fallback . replace ( "/" , `/${ locale } /` )
718
+ : newDynamicSsgRoute . fallback ;
719
+ newDynamicSsgRoute . routeRegex = localeSsgPages . dynamic [
720
+ newKey
721
+ ] . routeRegex . replace ( "^/" , `^/${ locale } /` ) ;
722
+ }
723
+
724
+ ssgPages . dynamic = {
725
+ ...ssgPages . dynamic ,
726
+ ...localeSsgPages . dynamic
727
+ } ;
728
+ }
729
+ }
730
+ }
731
+
585
732
const publicFiles = await this . readPublicFiles ( ) ;
586
733
587
734
publicFiles . forEach ( ( pf ) => {
@@ -727,26 +874,16 @@ class Builder {
727
874
) ;
728
875
const destination = path . join (
729
876
assetOutputDirectory ,
730
- withBasePath ( `_next/data/${ buildId } /${ localePrefixedJSONFileName } ` )
877
+ withBasePath (
878
+ `_next/data/${ buildId } /${
879
+ defaultLocale && defaultLocale === locale
880
+ ? JSONFileName
881
+ : localePrefixedJSONFileName
882
+ } `
883
+ )
731
884
) ;
732
885
733
- if ( defaultLocale && defaultLocale === locale ) {
734
- // If this is default locale, we need to copy to two destinations
735
- // the locale-prefixed path and non-locale-prefixed path
736
- const defaultDestination = path . join (
737
- assetOutputDirectory ,
738
- withBasePath ( `_next/data/${ buildId } /${ JSONFileName } ` )
739
- ) ;
740
-
741
- return new Promise ( async ( ) => {
742
- await Promise . all ( [
743
- copyIfExists ( source , destination ) ,
744
- copyIfExists ( source , defaultDestination )
745
- ] ) ;
746
- } ) ;
747
- } else {
748
- return copyIfExists ( source , destination ) ;
749
- }
886
+ return copyIfExists ( source , destination ) ;
750
887
} )
751
888
) ;
752
889
@@ -765,32 +902,22 @@ class Builder {
765
902
const destination = path . join (
766
903
assetOutputDirectory ,
767
904
withBasePath (
768
- path . join ( "static-pages" , buildId , localePrefixedPageFilePath )
905
+ path . join (
906
+ "static-pages" ,
907
+ buildId ,
908
+ defaultLocale && defaultLocale === locale
909
+ ? pageFilePath
910
+ : localePrefixedPageFilePath
911
+ )
769
912
)
770
913
) ;
771
914
772
- if ( defaultLocale && defaultLocale === locale ) {
773
- // If this is default locale, we need to copy to two destinations
774
- // the locale-prefixed path and non-locale-prefixed path
775
- const defaultDestination = path . join (
776
- assetOutputDirectory ,
777
- withBasePath ( path . join ( "static-pages" , buildId , pageFilePath ) )
778
- ) ;
779
-
780
- return new Promise ( async ( ) => {
781
- await Promise . all ( [
782
- copyIfExists ( source , destination ) ,
783
- copyIfExists ( source , defaultDestination )
784
- ] ) ;
785
- } ) ;
786
- } else {
787
- return copyIfExists ( source , destination ) ;
788
- }
915
+ return copyIfExists ( source , destination ) ;
789
916
} )
790
917
) ;
791
918
792
919
fallbackHTMLPageAssets . concat (
793
- Object . values ( prerenderManifest . dynamicRoutes || { } )
920
+ Object . values ( prerenderManifest . dynamicRoutes ?? { } )
794
921
. filter ( ( { fallback } ) => {
795
922
return ! ! fallback ;
796
923
} )
@@ -806,27 +933,17 @@ class Builder {
806
933
const destination = path . join (
807
934
assetOutputDirectory ,
808
935
withBasePath (
809
- path . join ( "static-pages" , buildId , localePrefixedFallback )
936
+ path . join (
937
+ "static-pages" ,
938
+ buildId ,
939
+ defaultLocale && defaultLocale === locale
940
+ ? fallback
941
+ : localePrefixedFallback
942
+ )
810
943
)
811
944
) ;
812
945
813
- if ( defaultLocale && defaultLocale === locale ) {
814
- // If this is default locale, we need to copy to two destinations
815
- // the locale-prefixed path and non-locale-prefixed path
816
- const defaultDestination = path . join (
817
- assetOutputDirectory ,
818
- withBasePath ( path . join ( "static-pages" , buildId , fallback ) )
819
- ) ;
820
-
821
- return new Promise ( async ( ) => {
822
- await Promise . all ( [
823
- copyIfExists ( source , destination ) ,
824
- copyIfExists ( source , defaultDestination )
825
- ] ) ;
826
- } ) ;
827
- } else {
828
- return copyIfExists ( source , destination ) ;
829
- }
946
+ return copyIfExists ( source , destination ) ;
830
947
} )
831
948
) ;
832
949
}
@@ -927,11 +1044,21 @@ class Builder {
927
1044
await restoreUserConfig ( ) ;
928
1045
}
929
1046
1047
+ const routesManifest = require ( join (
1048
+ this . dotNextDir ,
1049
+ "routes-manifest.json"
1050
+ ) ) ;
1051
+
1052
+ const prerenderManifest = require ( join (
1053
+ this . dotNextDir ,
1054
+ "prerender-manifest.json"
1055
+ ) ) ;
1056
+
930
1057
const {
931
1058
defaultBuildManifest,
932
1059
apiBuildManifest,
933
1060
imageBuildManifest
934
- } = await this . prepareBuildManifests ( ) ;
1061
+ } = await this . prepareBuildManifests ( routesManifest , prerenderManifest ) ;
935
1062
936
1063
await this . buildDefaultLambda ( defaultBuildManifest ) ;
937
1064
@@ -953,10 +1080,6 @@ class Builder {
953
1080
}
954
1081
955
1082
// Copy static assets to .serverless_nextjs directory
956
- const routesManifest = require ( join (
957
- this . dotNextDir ,
958
- "routes-manifest.json"
959
- ) ) ;
960
1083
await this . buildStaticAssets ( defaultBuildManifest , routesManifest ) ;
961
1084
}
962
1085
0 commit comments