1
1
const fs = require ( 'fs' )
2
+ const url = require ( 'url' )
2
3
const os = require ( 'os' )
3
4
const path = require ( 'path' )
4
5
const crypto = require ( 'crypto' )
5
6
const chokidar = require ( 'chokidar' )
6
7
const postcss = require ( 'postcss' )
8
+ const hash = require ( 'object-hash' )
7
9
const dlv = require ( 'dlv' )
8
10
const selectorParser = require ( 'postcss-selector-parser' )
9
11
const LRU = require ( 'quick-lru' )
@@ -21,6 +23,8 @@ const { isPlainObject } = require('./utils')
21
23
const { isBuffer } = require ( 'util' )
22
24
23
25
let contextMap = sharedState . contextMap
26
+ let configContextMap = sharedState . configContextMap
27
+ let contextSourcesMap = sharedState . contextSourcesMap
24
28
let env = sharedState . env
25
29
26
30
// Earmarks a directory for our touch files.
@@ -148,27 +152,29 @@ function getTailwindConfig(configOrPath) {
148
152
let userConfigPath = resolveConfigPath ( configOrPath )
149
153
150
154
if ( userConfigPath !== null ) {
151
- let [ prevConfig , prevModified = - Infinity ] = configPathCache . get ( userConfigPath ) ?? [ ]
155
+ let [ prevConfig , prevModified = - Infinity , prevConfigHash ] =
156
+ configPathCache . get ( userConfigPath ) ?? [ ]
152
157
let modified = fs . statSync ( userConfigPath ) . mtimeMs
153
158
154
159
// It hasn't changed (based on timestamp)
155
160
if ( modified <= prevModified ) {
156
- return [ prevConfig , userConfigPath ]
161
+ return [ prevConfig , userConfigPath , prevConfigHash ]
157
162
}
158
163
159
164
// It has changed (based on timestamp), or first run
160
165
delete require . cache [ userConfigPath ]
161
166
let newConfig = resolveConfig ( require ( userConfigPath ) )
162
- configPathCache . set ( userConfigPath , [ newConfig , modified ] )
163
- return [ newConfig , userConfigPath ]
167
+ let newHash = hash ( newConfig )
168
+ configPathCache . set ( userConfigPath , [ newConfig , modified , newHash ] )
169
+ return [ newConfig , userConfigPath , newHash ]
164
170
}
165
171
166
172
// It's a plain object, not a path
167
173
let newConfig = resolveConfig (
168
174
configOrPath . config === undefined ? configOrPath : configOrPath . config
169
175
)
170
176
171
- return [ newConfig , null ]
177
+ return [ newConfig , null , hash ( newConfig ) ]
172
178
}
173
179
174
180
let fileModifiedMap = new Map ( )
@@ -177,13 +183,14 @@ function trackModified(files) {
177
183
let changed = false
178
184
179
185
for ( let file of files ) {
180
- let newModified = fs . statSync ( file ) . mtimeMs
186
+ let pathname = url . parse ( file ) . pathname
187
+ let newModified = fs . statSync ( pathname ) . mtimeMs
181
188
182
- if ( ! fileModifiedMap . has ( file ) || newModified > fileModifiedMap . get ( file ) ) {
189
+ if ( ! fileModifiedMap . has ( pathname ) || newModified > fileModifiedMap . get ( pathname ) ) {
183
190
changed = true
184
191
}
185
192
186
- fileModifiedMap . set ( file , newModified )
193
+ fileModifiedMap . set ( pathname , newModified )
187
194
}
188
195
189
196
return changed
@@ -538,7 +545,7 @@ function cleanupContext(context) {
538
545
function setupContext ( configOrPath ) {
539
546
return ( result , root ) => {
540
547
let sourcePath = result . opts . from
541
- let [ tailwindConfig , userConfigPath ] = getTailwindConfig ( configOrPath )
548
+ let [ tailwindConfig , userConfigPath , tailwindConfigHash ] = getTailwindConfig ( configOrPath )
542
549
543
550
let contextDependencies = new Set ( )
544
551
contextDependencies . add ( sourcePath )
@@ -557,12 +564,38 @@ function setupContext(configOrPath) {
557
564
trackModified ( [ ...contextDependencies ] ) || userConfigPath === null
558
565
559
566
process . env . DEBUG && console . log ( 'Source path:' , sourcePath )
567
+
568
+ // If this file already has a context in the cache and we don't need to
569
+ // reset the context, return the cached context.
560
570
if ( contextMap . has ( sourcePath ) && ! contextDependenciesChanged ) {
561
571
return contextMap . get ( sourcePath )
562
572
}
563
573
574
+ // If the config file used already exists in the cache, return that.
575
+ console . log ( 'dependencies changed: ' , contextDependenciesChanged )
576
+ console . log ( tailwindConfigHash )
577
+ console . log ( configContextMap . keys ( ) )
578
+ console . log ( configContextMap . has ( tailwindConfigHash ) )
579
+
580
+ // DAMN YOU CONTEXTDEPENDENCIESCHANGED
581
+ // Ideas:
582
+ // - Can we incorporate the presence of @tailwind rules somehow? If it has no Tailwind rules, be
583
+ // more lenient about the dependencies changing?
584
+ if ( ! contextDependenciesChanged && configContextMap . has ( tailwindConfigHash ) ) {
585
+ let context = configContextMap . get ( tailwindConfigHash )
586
+ contextSourcesMap . get ( context ) . add ( sourcePath )
587
+ contextMap . set ( sourcePath , context )
588
+ return context
589
+ }
590
+
591
+ // TODO: Update this to no longer associate this path with its old context
592
+ // and clean up that context if no one else is using it.
564
593
if ( contextMap . has ( sourcePath ) ) {
565
- cleanupContext ( contextMap . get ( sourcePath ) )
594
+ let oldContext = contextMap . get ( sourcePath )
595
+ contextSourcesMap . get ( oldContext ) . remove ( sourcePath )
596
+ if ( contextSourcesMap . get ( oldContext ) . size === 0 ) {
597
+ cleanupContext ( oldContext )
598
+ }
566
599
}
567
600
568
601
process . env . DEBUG && console . log ( 'Setting up new context...' )
@@ -579,7 +612,6 @@ function setupContext(configOrPath) {
579
612
newPostCssNodeCache : new Map ( ) ,
580
613
candidateRuleMap : new Map ( ) ,
581
614
configPath : userConfigPath ,
582
- sourcePath : sourcePath ,
583
615
tailwindConfig : tailwindConfig ,
584
616
configDependencies : new Set ( ) ,
585
617
candidateFiles : Array . isArray ( tailwindConfig . purge )
@@ -588,8 +620,22 @@ function setupContext(configOrPath) {
588
620
variantMap : new Map ( ) ,
589
621
stylesheetCache : null ,
590
622
}
623
+
624
+ // ---
625
+
626
+ // Update all context tracking state
627
+
628
+ configContextMap . set ( tailwindConfigHash , context )
591
629
contextMap . set ( sourcePath , context )
592
630
631
+ if ( ! contextSourcesMap . has ( context ) ) {
632
+ contextSourcesMap . set ( context , new Set ( ) )
633
+ }
634
+
635
+ contextSourcesMap . get ( context ) . add ( sourcePath )
636
+
637
+ // ---
638
+
593
639
if ( userConfigPath !== null ) {
594
640
for ( let dependency of getModuleDependencies ( userConfigPath ) ) {
595
641
if ( dependency . file === userConfigPath ) {
@@ -600,6 +646,12 @@ function setupContext(configOrPath) {
600
646
}
601
647
}
602
648
649
+ let prev = null
650
+ for ( let [ key , value ] of contextSourcesMap ) {
651
+ console . log ( key === prev )
652
+ prev = key
653
+ }
654
+
603
655
rebootWatcher ( context )
604
656
605
657
let corePluginList = Object . entries ( corePlugins )
0 commit comments