@@ -11,7 +11,7 @@ import {
1111 createBuilder ,
1212 targetFromTargetString ,
1313} from '@angular-devkit/architect' ;
14- import { JsonObject , join , normalize , resolve , schema } from '@angular-devkit/core' ;
14+ import { JsonObject , join , normalize , resolve } from '@angular-devkit/core' ;
1515import { NodeJsSyncHost } from '@angular-devkit/core/node' ;
1616import * as fs from 'fs' ;
1717import * as path from 'path' ;
@@ -27,11 +27,6 @@ async function _renderUniversal(
2727 browserResult : BrowserBuilderOutput ,
2828 serverResult : ServerBuilderOutput ,
2929) : Promise < BrowserBuilderOutput > {
30- const browserIndexOutputPath = path . join ( browserResult . outputPath || '' , 'index.html' ) ;
31- const indexHtml = fs . readFileSync ( browserIndexOutputPath , 'utf8' ) ;
32- const serverBundlePath = await _getServerModuleBundlePath ( options , context , serverResult ) ;
33- const root = context . workspaceRoot ;
34-
3530 // Get browser target options.
3631 const browserTarget = targetFromTargetString ( options . browserTarget ) ;
3732 const rawBrowserOptions = await context . getTargetOptions ( browserTarget ) ;
@@ -42,65 +37,72 @@ async function _renderUniversal(
4237 ) ;
4338
4439 // Initialize zone.js
40+ const root = context . workspaceRoot ;
4541 const zonePackage = require . resolve ( 'zone.js' , { paths : [ root ] } ) ;
4642 await import ( zonePackage ) ;
4743
48- const {
49- AppServerModule,
50- AppServerModuleNgFactory,
51- renderModule,
52- renderModuleFactory,
53- } = await import ( serverBundlePath ) ;
54-
55- let renderModuleFn : ( module : unknown , options : { } ) => Promise < string > ;
56- let AppServerModuleDef : unknown ;
57-
58- if ( renderModuleFactory && AppServerModuleNgFactory ) {
59- renderModuleFn = renderModuleFactory ;
60- AppServerModuleDef = AppServerModuleNgFactory ;
61- } else if ( renderModule && AppServerModule ) {
62- renderModuleFn = renderModule ;
63- AppServerModuleDef = AppServerModule ;
64- } else {
65- throw new Error ( `renderModule method and/or AppServerModule were not exported from: ${ serverBundlePath } .` ) ;
44+ const host = new NodeJsSyncHost ( ) ;
45+ const projectName = context . target && context . target . project ;
46+ if ( ! projectName ) {
47+ throw new Error ( 'The builder requires a target.' ) ;
6648 }
6749
68- // Load platform server module renderer
69- const renderOpts = {
70- document : indexHtml ,
71- url : options . route ,
72- } ;
73-
74- const html = await renderModuleFn ( AppServerModuleDef , renderOpts ) ;
75- // Overwrite the client index file.
76- const outputIndexPath = options . outputIndexPath
77- ? path . join ( root , options . outputIndexPath )
78- : browserIndexOutputPath ;
79-
80- fs . writeFileSync ( outputIndexPath , html ) ;
81-
82- if ( browserOptions . serviceWorker ) {
83- const host = new NodeJsSyncHost ( ) ;
50+ const projectMetadata = await context . getProjectMetadata ( projectName ) ;
51+ const projectRoot = resolve (
52+ normalize ( root ) ,
53+ normalize ( ( projectMetadata . root as string ) || '' ) ,
54+ ) ;
8455
85- const projectName = context . target && context . target . project ;
86- if ( ! projectName ) {
87- throw new Error ( 'The builder requires a target.' ) ;
56+ for ( const outputPath of browserResult . outputPaths ) {
57+ const localeDirectory = path . relative ( browserResult . baseOutputPath , outputPath ) ;
58+ const browserIndexOutputPath = path . join ( outputPath , 'index.html' ) ;
59+ const indexHtml = fs . readFileSync ( browserIndexOutputPath , 'utf8' ) ;
60+ const serverBundlePath = await _getServerModuleBundlePath ( options , context , serverResult , localeDirectory ) ;
61+
62+ const {
63+ AppServerModule,
64+ AppServerModuleNgFactory,
65+ renderModule,
66+ renderModuleFactory,
67+ } = await import ( serverBundlePath ) ;
68+
69+ let renderModuleFn : ( module : unknown , options : { } ) => Promise < string > ;
70+ let AppServerModuleDef : unknown ;
71+
72+ if ( renderModuleFactory && AppServerModuleNgFactory ) {
73+ renderModuleFn = renderModuleFactory ;
74+ AppServerModuleDef = AppServerModuleNgFactory ;
75+ } else if ( renderModule && AppServerModule ) {
76+ renderModuleFn = renderModule ;
77+ AppServerModuleDef = AppServerModule ;
78+ } else {
79+ throw new Error ( `renderModule method and/or AppServerModule were not exported from: ${ serverBundlePath } .` ) ;
8880 }
8981
90- const projectMetadata = await context . getProjectMetadata ( projectName ) ;
91- const projectRoot = resolve (
92- normalize ( context . workspaceRoot ) ,
93- normalize ( ( projectMetadata . root as string ) || '' ) ,
94- ) ;
95-
96- await augmentAppWithServiceWorker (
97- host ,
98- normalize ( root ) ,
99- projectRoot ,
100- join ( normalize ( root ) , browserOptions . outputPath ) ,
101- browserOptions . baseHref || '/' ,
102- browserOptions . ngswConfigPath ,
103- ) ;
82+ // Load platform server module renderer
83+ const renderOpts = {
84+ document : indexHtml ,
85+ url : options . route ,
86+ } ;
87+
88+ const html = await renderModuleFn ( AppServerModuleDef , renderOpts ) ;
89+ // Overwrite the client index file.
90+ const outputIndexPath = options . outputIndexPath
91+ ? path . join ( root , options . outputIndexPath )
92+ : browserIndexOutputPath ;
93+
94+ fs . writeFileSync ( outputIndexPath , html ) ;
95+
96+ if ( browserOptions . serviceWorker ) {
97+ await augmentAppWithServiceWorker (
98+ host ,
99+ normalize ( root ) ,
100+ projectRoot ,
101+ normalize ( outputPath ) ,
102+ browserOptions . baseHref || '/' ,
103+ browserOptions . ngswConfigPath ,
104+ ) ;
105+ }
104106 }
105107
106108 return browserResult ;
@@ -110,11 +112,18 @@ async function _getServerModuleBundlePath(
110112 options : BuildWebpackAppShellSchema ,
111113 context : BuilderContext ,
112114 serverResult : ServerBuilderOutput ,
115+ browserLocaleDirectory : string ,
113116) {
114117 if ( options . appModuleBundle ) {
115118 return path . join ( context . workspaceRoot , options . appModuleBundle ) ;
116119 } else {
117- const outputPath = serverResult . outputPath || '/' ;
120+ const { baseOutputPath = '' } = serverResult ;
121+ const outputPath = path . join ( baseOutputPath , browserLocaleDirectory ) ;
122+
123+ if ( ! fs . existsSync ( outputPath ) ) {
124+ throw new Error ( `Could not find server output directory: ${ outputPath } .` ) ;
125+ }
126+
118127 const files = fs . readdirSync ( outputPath , 'utf8' ) ;
119128 const re = / ^ m a i n \. (?: [ a - z A - Z 0 - 9 ] { 20 } \. ) ? (?: b u n d l e \. ) ? j s $ / ;
120129 const maybeMain = files . filter ( x => re . test ( x ) ) [ 0 ] ;
@@ -140,15 +149,17 @@ async function _appShellBuilder(
140149 watch : false ,
141150 serviceWorker : false ,
142151 } ) ;
143- const serverTargetRun = await context . scheduleTarget ( serverTarget , { } ) ;
152+ const serverTargetRun = await context . scheduleTarget ( serverTarget , {
153+ watch : false ,
154+ } ) ;
144155
145156 try {
146157 const [ browserResult , serverResult ] = await Promise . all ( [
147- ( browserTargetRun . result as { } ) as BrowserBuilderOutput ,
148- serverTargetRun . result ,
158+ browserTargetRun . result as unknown as BrowserBuilderOutput ,
159+ serverTargetRun . result as unknown as ServerBuilderOutput ,
149160 ] ) ;
150161
151- if ( browserResult . success === false || browserResult . outputPath === undefined ) {
162+ if ( browserResult . success === false || browserResult . baseOutputPath === undefined ) {
152163 return browserResult ;
153164 } else if ( serverResult . success === false ) {
154165 return serverResult ;
0 commit comments