@@ -10,6 +10,8 @@ import { ExecutionTransformer } from '@angular-architects/build-angular';
10
10
import * as path from 'path' ;
11
11
import * as fs from 'fs' ;
12
12
import {
13
+ hashFile ,
14
+ logger ,
13
15
NormalizedFederationConfig ,
14
16
setLogLevel ,
15
17
} from '@softarc/native-federation/build' ;
@@ -23,6 +25,8 @@ import { getExternals } from '@softarc/native-federation/build';
23
25
import { loadFederationConfig } from '@softarc/native-federation/build' ;
24
26
import { buildForFederation } from '@softarc/native-federation/build' ;
25
27
28
+ import * as crossSpawn from 'cross-spawn' ;
29
+
26
30
export async function runBuilder (
27
31
options : Schema ,
28
32
context : BuilderContext
@@ -41,6 +45,8 @@ export async function runBuilder(
41
45
const config = await loadFederationConfig ( fedOptions ) ;
42
46
const externals = getExternals ( config ) ;
43
47
48
+ runNgccIfNeeded ( fedOptions , fedOptions . workspaceRoot ) ;
49
+
44
50
options . externalDependencies = externals . filter ( ( e ) => e !== 'tslib' ) ;
45
51
const output = await build ( config , options , context ) ;
46
52
@@ -53,6 +59,83 @@ export async function runBuilder(
53
59
54
60
export default createBuilder ( runBuilder ) ;
55
61
62
+ function runNgccIfNeeded ( fedOptions : FederationOptions , workspaceRoot : string ) {
63
+ const hash = getLockFileHash ( fedOptions ) ;
64
+ const skip = skipNgcc ( hash , workspaceRoot ) ;
65
+
66
+ if ( ! skip ) {
67
+ runNgcc ( workspaceRoot ) ;
68
+ writeNgccLock ( hash , workspaceRoot ) ;
69
+ }
70
+ }
71
+
72
+ function runNgcc ( workspaceRoot : string ) {
73
+ logger . verbose ( 'Running ngcc' ) ;
74
+ const command = getNpxCommand ( workspaceRoot ) ;
75
+ const result = crossSpawn . sync ( command , [
76
+ 'ngcc' ,
77
+ '--async' ,
78
+ '--create-ivy-entry-points' ,
79
+ '--first-only'
80
+ ] , { stdio : 'inherit' } ) ;
81
+
82
+ if ( result . status !== 0 ) {
83
+ const error = result . error || '' ;
84
+ logger . error ( 'Error running ngcc: ' + error ) ;
85
+ }
86
+ }
87
+
88
+ function getLockFileHash ( fedOptions : FederationOptions ) {
89
+ const lockFileName = getLockFileName ( fedOptions . workspaceRoot ) ;
90
+ const hash = hashFile ( lockFileName ) ;
91
+ return hash ;
92
+ }
93
+
94
+ const NGCC_LOCK_DIR = 'node_modules/.cache/native-federation/ngcc' ;
95
+
96
+ function skipNgcc ( hash : string , workspaceRoot : string ) {
97
+
98
+ const ngccLockFileDir = path . join ( workspaceRoot , NGCC_LOCK_DIR ) ;
99
+ const ngccLockFileName = path . join ( ngccLockFileDir , hash + '.lock' ) ;
100
+
101
+ let exists = false ;
102
+ if ( fs . existsSync ( ngccLockFileName ) ) {
103
+ exists = true ;
104
+ }
105
+ return exists ;
106
+ }
107
+
108
+ function writeNgccLock ( hash : string , workspaceRoot : string ) {
109
+ const ngccLockFileDir = path . join ( workspaceRoot , NGCC_LOCK_DIR ) ;
110
+ const ngccLockFileName = path . join ( ngccLockFileDir , hash + '.lock' ) ;
111
+
112
+ if ( ! fs . existsSync ( ngccLockFileDir ) ) {
113
+ fs . mkdirSync ( ngccLockFileDir , { recursive : true } ) ;
114
+ }
115
+
116
+ fs . writeFileSync ( ngccLockFileName , '' ) ;
117
+ }
118
+
119
+ function getLockFileName ( workspaceRoot : string ) {
120
+ let candPath = '' ;
121
+ for ( const candLock of [ 'package-lock.json' , 'yarn.lock' , 'pnpm-lock.yaml' ] ) {
122
+ candPath = path . join ( workspaceRoot , candLock ) ;
123
+ if ( fs . existsSync ( candPath ) ) {
124
+ break ;
125
+ }
126
+ }
127
+ return candPath ;
128
+ }
129
+
130
+ function getNpxCommand ( workspaceRoot : string ) : string {
131
+ switch ( getLockFileName ( workspaceRoot ) ) {
132
+ case 'package-lock.json' : return 'npx' ;
133
+ case 'yarn.lock' : return 'yarn' ;
134
+ case 'pnpm-lock.yaml' : return 'pnpx' ;
135
+ default : return 'npx' ;
136
+ }
137
+ }
138
+
56
139
function updateIndexHtml ( fedOptions : FederationOptions ) {
57
140
const outputPath = path . join ( fedOptions . workspaceRoot , fedOptions . outputPath ) ;
58
141
const indexPath = path . join ( outputPath , 'index.html' ) ;
0 commit comments