1
1
import watcher from '@parcel/watcher'
2
- import {
3
- IO ,
4
- Parsing ,
5
- clearCache ,
6
- scanDir ,
7
- scanFiles ,
8
- type ChangedContent ,
9
- } from '@tailwindcss/oxide'
2
+ import { IO , Parsing , scanDir , scanFiles , type ChangedContent } from '@tailwindcss/oxide'
10
3
import { existsSync } from 'node:fs'
11
4
import fs from 'node:fs/promises'
12
5
import path from 'node:path'
@@ -99,25 +92,42 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
99
92
args [ '--input' ] ?? base ,
100
93
)
101
94
102
- // Compile the input
103
- let { build } = compile ( input )
104
- let result = build ( candidates )
105
-
106
- // Optimize the output
107
- if ( args [ '--minify' ] || args [ '--optimize' ] ) {
108
- result = optimizeCss ( result , {
109
- file : args [ '--input' ] ?? 'input.css' ,
110
- minify : args [ '--minify' ] ?? false ,
111
- } )
95
+ let previous = {
96
+ css : '' ,
97
+ optimizedCss : '' ,
112
98
}
113
99
114
- // Write the output
115
- if ( args [ '--output' ] ) {
116
- await outputFile ( args [ '--output' ] , result )
117
- } else {
118
- println ( result )
100
+ async function write ( css : string , args : Result < ReturnType < typeof options > > ) {
101
+ let output = css
102
+
103
+ // Optimize the output
104
+ if ( args [ '--minify' ] || args [ '--optimize' ] ) {
105
+ if ( css !== previous . css ) {
106
+ let optimizedCss = optimizeCss ( css , {
107
+ file : args [ '--input' ] ?? 'input.css' ,
108
+ minify : args [ '--minify' ] ?? false ,
109
+ } )
110
+ previous . css = css
111
+ previous . optimizedCss = optimizedCss
112
+ output = optimizedCss
113
+ } else {
114
+ output = previous . optimizedCss
115
+ }
116
+ }
117
+
118
+ // Write the output
119
+ if ( args [ '--output' ] ) {
120
+ await outputFile ( args [ '--output' ] , output )
121
+ } else {
122
+ println ( output )
123
+ }
119
124
}
120
125
126
+ // Compile the input
127
+ let { build } = compile ( input )
128
+
129
+ await write ( build ( candidates ) , args )
130
+
121
131
let end = process . hrtime . bigint ( )
122
132
eprintln ( header ( ) )
123
133
eprintln ( )
@@ -162,26 +172,14 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
162
172
// Re-compile the input
163
173
let start = process . hrtime . bigint ( )
164
174
175
+ // Track the compiled CSS
176
+ let compiledCss = ''
177
+
165
178
// Scan the entire `base` directory for full rebuilds.
166
179
if ( rebuildStrategy === 'full' ) {
167
- // Clear the cache because we need to re-scan the entire directory.
168
- clearCache ( )
169
-
170
180
// Re-scan the directory to get the new `candidates`.
171
181
candidates = scanDir ( { base } ) . candidates
172
- }
173
-
174
- // Scan changed files only for incremental rebuilds.
175
- else if ( rebuildStrategy === 'incremental' ) {
176
- let uniqueCandidates = new Set ( candidates )
177
- for ( let candidate of scanFiles ( changedFiles , IO . Sequential | Parsing . Sequential ) ) {
178
- uniqueCandidates . add ( candidate )
179
- }
180
- candidates = Array . from ( uniqueCandidates )
181
- }
182
182
183
- // Resolve the input
184
- if ( rebuildStrategy === 'full' ) {
185
183
// Collect the new `input` and `cssImportPaths`.
186
184
; [ input , cssImportPaths ] = await handleImports (
187
185
args [ '--input' ]
@@ -191,25 +189,19 @@ export async function handle(args: Result<ReturnType<typeof options>>) {
191
189
` ,
192
190
args [ '--input' ] ?? base ,
193
191
)
192
+
193
+ build = compile ( input ) . build
194
+ compiledCss = build ( candidates )
194
195
}
195
196
196
- // Compile the input
197
- result = compile ( input ) . build ( candidates )
197
+ // Scan changed files only for incremental rebuilds.
198
+ else if ( rebuildStrategy === 'incremental' ) {
199
+ let newCandidates = scanFiles ( changedFiles , IO . Sequential | Parsing . Sequential )
198
200
199
- // Optimize the output
200
- if ( args [ '--minify' ] || args [ '--optimize' ] ) {
201
- result = optimizeCss ( result , {
202
- file : args [ '--input' ] ?? 'input.css' ,
203
- minify : args [ '--minify' ] ?? false ,
204
- } )
201
+ compiledCss = build ( newCandidates )
205
202
}
206
203
207
- // Write the output
208
- if ( args [ '--output' ] ) {
209
- await outputFile ( args [ '--output' ] , result )
210
- } else {
211
- println ( result )
212
- }
204
+ await write ( compiledCss , args )
213
205
214
206
let end = process . hrtime . bigint ( )
215
207
eprintln ( `Done in ${ formatDuration ( end - start ) } ` )
@@ -244,7 +236,9 @@ function handleImports(
244
236
// Relevant specification:
245
237
// - CSS Import Resolve: https://csstools.github.io/css-import-resolve/
246
238
247
- if ( ! input . includes ( '@import' ) ) return [ input , [ ] ]
239
+ if ( ! input . includes ( '@import' ) ) {
240
+ return [ input , [ file ] ]
241
+ }
248
242
249
243
return postcss ( )
250
244
. use ( atImport ( ) )
@@ -254,6 +248,8 @@ function handleImports(
254
248
255
249
// Use `result.messages` to get the imported files. This also includes the
256
250
// current file itself.
257
- result . messages . filter ( ( msg ) => msg . type === 'postcss-import' ) . map ( ( msg ) => msg . file ) ,
251
+ [ file ] . concat (
252
+ result . messages . filter ( ( msg ) => msg . type === 'dependency' ) . map ( ( msg ) => msg . file ) ,
253
+ ) ,
258
254
] )
259
255
}
0 commit comments