88
99import { BuilderContext , BuilderOutput , createBuilder } from '@angular-devkit/architect' ;
1010import type { BuildOptions , Metafile , OutputFile } from 'esbuild' ;
11- import assert from 'node:assert' ;
1211import { constants as fsConstants } from 'node:fs' ;
1312import fs from 'node:fs/promises' ;
1413import path from 'node:path' ;
@@ -26,18 +25,16 @@ import { logBuilderStatusWarnings } from './builder-status-warnings';
2625import { checkCommonJSModules } from './commonjs-checker' ;
2726import { BundlerContext , logMessages } from './esbuild' ;
2827import { createGlobalScriptsBundleOptions } from './global-scripts' ;
28+ import { createGlobalStylesBundleOptions } from './global-styles' ;
2929import { extractLicenses } from './license-extractor' ;
30- import { LoadResultCache } from './load-result-cache' ;
3130import { BrowserEsbuildOptions , NormalizedBrowserOptions , normalizeOptions } from './options' ;
3231import { Schema as BrowserBuilderOptions } from './schema' ;
3332import { createSourcemapIngorelistPlugin } from './sourcemap-ignorelist-plugin' ;
34- import { createStylesheetBundleOptions } from './stylesheets/bundle-options' ;
3533import { shutdownSassWorkerPool } from './stylesheets/sass-plugin' ;
3634import type { ChangedFiles } from './watcher' ;
3735
3836interface RebuildState {
39- codeRebuild ?: BundlerContext ;
40- globalStylesRebuild ?: BundlerContext ;
37+ rebuildContexts : BundlerContext [ ] ;
4138 codeBundleCache ?: SourceFileCache ;
4239 fileChanges : ChangedFiles ;
4340}
@@ -50,8 +47,7 @@ class ExecutionResult {
5047 readonly assetFiles : { source : string ; destination : string } [ ] = [ ] ;
5148
5249 constructor (
53- private codeRebuild ?: BundlerContext ,
54- private globalStylesRebuild ?: BundlerContext ,
50+ private rebuildContexts : BundlerContext [ ] ,
5551 private codeBundleCache ?: SourceFileCache ,
5652 ) { }
5753
@@ -77,15 +73,14 @@ class ExecutionResult {
7773 this . codeBundleCache ?. invalidate ( [ ...fileChanges . modified , ...fileChanges . removed ] ) ;
7874
7975 return {
80- codeRebuild : this . codeRebuild ,
81- globalStylesRebuild : this . globalStylesRebuild ,
76+ rebuildContexts : this . rebuildContexts ,
8277 codeBundleCache : this . codeBundleCache ,
8378 fileChanges,
8479 } ;
8580 }
8681
8782 async dispose ( ) : Promise < void > {
88- await Promise . allSettled ( [ this . codeRebuild ?. dispose ( ) , this . globalStylesRebuild ?. dispose ( ) ] ) ;
83+ await Promise . allSettled ( this . rebuildContexts . map ( ( context ) => context . dispose ( ) ) ) ;
8984 }
9085}
9186
@@ -109,57 +104,55 @@ async function execute(
109104 const target = transformSupportedBrowsersToTargets ( browsers ) ;
110105
111106 // Reuse rebuild state or create new bundle contexts for code and global stylesheets
112- const bundlerContexts = [ ] ;
113-
114- // Application code
107+ let bundlerContexts = rebuildState ?. rebuildContexts ;
115108 const codeBundleCache = options . watch
116109 ? rebuildState ?. codeBundleCache ?? new SourceFileCache ( )
117110 : undefined ;
118- const codeBundleContext =
119- rebuildState ?. codeRebuild ??
120- new BundlerContext (
121- workspaceRoot ,
122- ! ! options . watch ,
123- createCodeBundleOptions ( options , target , browsers , codeBundleCache ) ,
124- ) ;
125- bundlerContexts . push ( codeBundleContext ) ;
126- // Global Stylesheets
127- let globalStylesBundleContext ;
128- if ( options . globalStyles . length > 0 ) {
129- globalStylesBundleContext =
130- rebuildState ?. globalStylesRebuild ??
111+ if ( bundlerContexts === undefined ) {
112+ bundlerContexts = [ ] ;
113+
114+ // Application code
115+ bundlerContexts . push (
131116 new BundlerContext (
132117 workspaceRoot ,
133118 ! ! options . watch ,
134- createGlobalStylesBundleOptions (
119+ createCodeBundleOptions ( options , target , browsers , codeBundleCache ) ,
120+ ) ,
121+ ) ;
122+
123+ // Global Stylesheets
124+ if ( options . globalStyles . length > 0 ) {
125+ for ( const initial of [ true , false ] ) {
126+ const bundleOptions = createGlobalStylesBundleOptions (
135127 options ,
136128 target ,
137129 browsers ,
130+ initial ,
138131 codeBundleCache ?. loadResultCache ,
139- ) ,
140- ) ;
141- bundlerContexts . push ( globalStylesBundleContext ) ;
142- }
143- // Global Scripts
144- if ( options . globalScripts . length > 0 ) {
145- const globalScriptsBundleContext = new BundlerContext (
146- workspaceRoot ,
147- ! ! options . watch ,
148- createGlobalScriptsBundleOptions ( options ) ,
149- ) ;
150- bundlerContexts . push ( globalScriptsBundleContext ) ;
132+ ) ;
133+ if ( bundleOptions ) {
134+ bundlerContexts . push ( new BundlerContext ( workspaceRoot , ! ! options . watch , bundleOptions ) ) ;
135+ }
136+ }
137+ }
138+
139+ // Global Scripts
140+ if ( options . globalScripts . length > 0 ) {
141+ for ( const initial of [ true , false ] ) {
142+ const bundleOptions = createGlobalScriptsBundleOptions ( options , initial ) ;
143+ if ( bundleOptions ) {
144+ bundlerContexts . push ( new BundlerContext ( workspaceRoot , ! ! options . watch , bundleOptions ) ) ;
145+ }
146+ }
147+ }
151148 }
152149
153150 const bundlingResult = await BundlerContext . bundleAll ( bundlerContexts ) ;
154151
155152 // Log all warnings and errors generated during bundling
156153 await logMessages ( context , bundlingResult ) ;
157154
158- const executionResult = new ExecutionResult (
159- codeBundleContext ,
160- globalStylesBundleContext ,
161- codeBundleCache ,
162- ) ;
155+ const executionResult = new ExecutionResult ( bundlerContexts , codeBundleCache ) ;
163156
164157 // Return if the bundling has errors
165158 if ( bundlingResult . errors ) {
@@ -501,76 +494,6 @@ function getFeatureSupport(target: string[]): BuildOptions['supported'] {
501494 return supported ;
502495}
503496
504- function createGlobalStylesBundleOptions (
505- options : NormalizedBrowserOptions ,
506- target : string [ ] ,
507- browsers : string [ ] ,
508- cache ?: LoadResultCache ,
509- ) : BuildOptions {
510- const {
511- workspaceRoot,
512- optimizationOptions,
513- sourcemapOptions,
514- outputNames,
515- globalStyles,
516- preserveSymlinks,
517- externalDependencies,
518- stylePreprocessorOptions,
519- tailwindConfiguration,
520- } = options ;
521-
522- const buildOptions = createStylesheetBundleOptions (
523- {
524- workspaceRoot,
525- optimization : ! ! optimizationOptions . styles . minify ,
526- sourcemap : ! ! sourcemapOptions . styles ,
527- preserveSymlinks,
528- target,
529- externalDependencies,
530- outputNames,
531- includePaths : stylePreprocessorOptions ?. includePaths ,
532- browsers,
533- tailwindConfiguration,
534- } ,
535- cache ,
536- ) ;
537- buildOptions . legalComments = options . extractLicenses ? 'none' : 'eof' ;
538-
539- const namespace = 'angular:styles/global' ;
540- buildOptions . entryPoints = { } ;
541- for ( const { name } of globalStyles ) {
542- buildOptions . entryPoints [ name ] = `${ namespace } ;${ name } ` ;
543- }
544-
545- buildOptions . plugins . unshift ( {
546- name : 'angular-global-styles' ,
547- setup ( build ) {
548- build . onResolve ( { filter : / ^ a n g u l a r : s t y l e s \/ g l o b a l ; / } , ( args ) => {
549- if ( args . kind !== 'entry-point' ) {
550- return null ;
551- }
552-
553- return {
554- path : args . path . split ( ';' , 2 ) [ 1 ] ,
555- namespace,
556- } ;
557- } ) ;
558- build . onLoad ( { filter : / ./ , namespace } , ( args ) => {
559- const files = globalStyles . find ( ( { name } ) => name === args . path ) ?. files ;
560- assert ( files , `global style name should always be found [${ args . path } ]` ) ;
561-
562- return {
563- contents : files . map ( ( file ) => `@import '${ file . replace ( / \\ / g, '/' ) } ';` ) . join ( '\n' ) ,
564- loader : 'css' ,
565- resolveDir : workspaceRoot ,
566- } ;
567- } ) ;
568- } ,
569- } ) ;
570-
571- return buildOptions ;
572- }
573-
574497async function withSpinner < T > ( text : string , action : ( ) => T | Promise < T > ) : Promise < T > {
575498 const spinner = new Spinner ( text ) ;
576499 spinner . start ( ) ;
0 commit comments