@@ -96,76 +96,30 @@ export interface StylesheetLanguage {
9696const postcssProcessors = new Map < string , WeakRef < PostcssProcessor > > ( ) ;
9797
9898export class StylesheetPluginFactory {
99- private postcssProcessor ?: PostcssProcessor ;
100-
10199 constructor (
102100 private readonly options : StylesheetPluginOptions ,
103101 private readonly cache ?: LoadResultCache ,
104102 ) { }
105103
106104 create ( language : Readonly < StylesheetLanguage > ) : Plugin {
105+ const { cache, options, setupPostcss } = this ;
106+
107107 // Return a noop plugin if no load actions are required
108- if (
109- ! language . process &&
110- ! this . options . postcssConfiguration &&
111- ! this . options . tailwindConfiguration
112- ) {
108+ if ( ! language . process && ! options . postcssConfiguration && ! options . tailwindConfiguration ) {
113109 return {
114110 name : 'angular-' + language . name ,
115111 setup ( ) { } ,
116112 } ;
117113 }
118114
119- const { cache, options } = this ;
120- const setupPostcss = async ( ) => {
121- // Return already created processor if present
122- if ( this . postcssProcessor ) {
123- return this . postcssProcessor ;
124- }
125-
126- if ( options . postcssConfiguration ) {
127- const postCssInstanceKey = JSON . stringify ( options . postcssConfiguration ) ;
128-
129- this . postcssProcessor = postcssProcessors . get ( postCssInstanceKey ) ?. deref ( ) ;
130-
131- if ( ! this . postcssProcessor ) {
132- postcss ??= ( await import ( 'postcss' ) ) . default ;
133- this . postcssProcessor = postcss ( ) ;
134-
135- for ( const [ pluginName , pluginOptions ] of options . postcssConfiguration . plugins ) {
136- const { default : plugin } = await import ( pluginName ) ;
137- if ( typeof plugin !== 'function' || plugin . postcss !== true ) {
138- throw new Error ( `Attempted to load invalid Postcss plugin: "${ pluginName } "` ) ;
139- }
140- this . postcssProcessor . use ( plugin ( pluginOptions ) ) ;
141- }
142-
143- postcssProcessors . set ( postCssInstanceKey , new WeakRef ( this . postcssProcessor ) ) ;
144- }
145- } else if ( options . tailwindConfiguration ) {
146- const { package : tailwindPackage , file : config } = options . tailwindConfiguration ;
147- const postCssInstanceKey = tailwindPackage + ':' + config ;
148- this . postcssProcessor = postcssProcessors . get ( postCssInstanceKey ) ?. deref ( ) ;
149-
150- if ( ! this . postcssProcessor ) {
151- postcss ??= ( await import ( 'postcss' ) ) . default ;
152- const tailwind = await import ( tailwindPackage ) ;
153- this . postcssProcessor = postcss ( ) . use ( tailwind . default ( { config } ) ) ;
154- postcssProcessors . set ( postCssInstanceKey , new WeakRef ( this . postcssProcessor ) ) ;
155- }
156- }
157-
158- return this . postcssProcessor ;
159- } ;
160-
161115 return {
162116 name : 'angular-' + language . name ,
163117 async setup ( build ) {
164118 // Setup postcss if needed
165119 let postcssProcessor : PostcssProcessor | undefined ;
166120 build . onStart ( async ( ) => {
167121 try {
168- postcssProcessor = await setupPostcss ( ) ;
122+ postcssProcessor = await setupPostcss ;
169123 } catch {
170124 return {
171125 errors : [
@@ -229,6 +183,56 @@ export class StylesheetPluginFactory {
229183 } ,
230184 } ;
231185 }
186+
187+ private setupPostcssPromise : Promise < PostcssProcessor | undefined > | undefined ;
188+ private get setupPostcss ( ) : Promise < PostcssProcessor | undefined > {
189+ return ( this . setupPostcssPromise ??= this . initPostcss ( ) ) ;
190+ }
191+
192+ private initPostcssCallCount = 0 ;
193+ /**
194+ * This method should not be called directly.
195+ * Use {@link setupPostcss} instead.
196+ */
197+ private async initPostcss ( ) : Promise < PostcssProcessor | undefined > {
198+ assert . equal ( ++ this . initPostcssCallCount , 1 , '`initPostcss` was called more than once.' ) ;
199+
200+ const { options } = this ;
201+ if ( options . postcssConfiguration ) {
202+ const postCssInstanceKey = JSON . stringify ( options . postcssConfiguration ) ;
203+ let postcssProcessor = postcssProcessors . get ( postCssInstanceKey ) ?. deref ( ) ;
204+
205+ if ( ! postcssProcessor ) {
206+ postcss ??= ( await import ( 'postcss' ) ) . default ;
207+ postcssProcessor = postcss ( ) ;
208+ for ( const [ pluginName , pluginOptions ] of options . postcssConfiguration . plugins ) {
209+ const { default : plugin } = await import ( pluginName ) ;
210+ if ( typeof plugin !== 'function' || plugin . postcss !== true ) {
211+ throw new Error ( `Attempted to load invalid Postcss plugin: "${ pluginName } "` ) ;
212+ }
213+
214+ postcssProcessor . use ( plugin ( pluginOptions ) ) ;
215+ }
216+
217+ postcssProcessors . set ( postCssInstanceKey , new WeakRef ( postcssProcessor ) ) ;
218+ }
219+
220+ return postcssProcessor ;
221+ } else if ( options . tailwindConfiguration ) {
222+ const { package : tailwindPackage , file : config } = options . tailwindConfiguration ;
223+ const postCssInstanceKey = tailwindPackage + ':' + config ;
224+ let postcssProcessor = postcssProcessors . get ( postCssInstanceKey ) ?. deref ( ) ;
225+
226+ if ( ! postcssProcessor ) {
227+ postcss ??= ( await import ( 'postcss' ) ) . default ;
228+ const tailwind = await import ( tailwindPackage ) ;
229+ postcssProcessor = postcss ( ) . use ( tailwind . default ( { config } ) ) ;
230+ postcssProcessors . set ( postCssInstanceKey , new WeakRef ( postcssProcessor ) ) ;
231+ }
232+
233+ return postcssProcessor ;
234+ }
235+ }
232236}
233237
234238async function processStylesheet (
0 commit comments