1
- import { utimes } from 'fs/promises'
2
1
import * as path from 'upath'
3
- import _debug from 'debug'
4
- import { normalizePath as normalizeVitePath } from 'vite'
5
- import { cacheDir , writeStyles , resolveVuetifyBase , normalizePath } from '@vuetify/loader-shared'
2
+ import { resolveVuetifyBase , normalizePath } from '@vuetify/loader-shared'
6
3
7
- import type { Plugin , ViteDevServer } from 'vite'
4
+ import type { Plugin } from 'vite'
8
5
import type { Options } from '@vuetify/loader-shared'
9
- import type { PluginContext } from 'rollup'
10
-
11
- const debug = _debug ( 'vuetify:styles' )
12
6
13
7
function isSubdir ( root : string , test : string ) {
14
8
const relative = path . relative ( root , test )
15
9
return relative && ! relative . startsWith ( '..' ) && ! path . isAbsolute ( relative )
16
10
}
17
11
18
- const styleImportRegexp = / ( @ u s e | m e t a \. l o a d - c s s \( ) [ ' " ] ( v u e t i f y (?: \/ l i b ) ? (?: \/ s t y l e s (?: \/ m a i n (?: \. s a s s ) ? ) ? ) ? ) [ ' " ] /
19
-
20
12
export function stylesPlugin ( options : Options ) : Plugin {
21
13
const vuetifyBase = resolveVuetifyBase ( )
22
- const files = new Set < string > ( )
23
-
24
- let server : ViteDevServer
25
- let context : PluginContext
26
- let resolve : ( v : boolean ) => void
27
- let promise : Promise < boolean > | null
28
- let needsTouch = false
29
- const blockingModules = new Set < string > ( )
30
-
31
- let pendingModules : string [ ]
32
- async function getPendingModules ( ) {
33
- if ( ! server ) {
34
- await new Promise ( resolve => setTimeout ( resolve , 0 ) )
35
- const modules = Array . from ( context . getModuleIds ( ) )
36
- . filter ( id => {
37
- return ! blockingModules . has ( id ) && // Ignore the current file
38
- ! / \w \. ( s [ a c ] | c ) s s / . test ( id ) // Ignore stylesheets
39
- } )
40
- . map ( id => context . getModuleInfo ( id ) ! )
41
- . filter ( module => module . code == null ) // Ignore already loaded modules
42
-
43
- pendingModules = modules . map ( module => module . id )
44
- if ( ! pendingModules . length ) return 0
45
-
46
- const promises = modules . map ( module => context . load ( module ) )
47
- await Promise . race ( promises )
48
-
49
- return promises . length
50
- } else {
51
- const modules = Array . from ( server . moduleGraph . urlToModuleMap . entries ( ) )
52
- . filter ( ( [ k , v ] ) => (
53
- v . transformResult == null && // Ignore already loaded modules
54
- ! k . startsWith ( '/@id/' ) &&
55
- ! / \w \. ( s [ a c ] | c ) s s / . test ( k ) && // Ignore stylesheets
56
- ! blockingModules . has ( v . id ! ) && // Ignore the current file
57
- ! / \/ n o d e _ m o d u l e s \/ \. v i t e \/ d e p s \/ (? ! v u e t i f y [ . _ ] ) / . test ( k ) // Ignore dependencies
58
- ) )
59
-
60
- pendingModules = modules . map ( ( [ , v ] ) => v . id ! )
61
- if ( ! pendingModules . length ) return 0
62
-
63
- const promises = modules . map ( ( [ k , v ] ) => server . transformRequest ( k ) . then ( ( ) => v ) )
64
- await Promise . race ( promises )
65
-
66
- return promises . length
67
- }
68
- }
69
-
70
- let timeout : NodeJS . Timeout
71
- async function awaitBlocking ( ) {
72
- let pending
73
- do {
74
- clearTimeout ( timeout )
75
- timeout = setTimeout ( ( ) => {
76
- console . error ( 'vuetify:styles fallback timeout hit' , {
77
- blockingModules : Array . from ( blockingModules . values ( ) ) ,
78
- pendingModules,
79
- pendingRequests : server ?. _pendingRequests . keys ( )
80
- } )
81
- resolve ( false )
82
- } , options . stylesTimeout )
83
-
84
- pending = await Promise . any < boolean | number | null > ( [
85
- promise ,
86
- getPendingModules ( )
87
- ] )
88
- debug ( pending , 'pending modules' , pendingModules )
89
- } while ( pending )
90
-
91
- resolve ( false )
92
- }
93
-
94
- async function awaitResolve ( id ?: string ) {
95
- if ( id ) {
96
- blockingModules . add ( id )
97
- }
98
-
99
- if ( ! promise ) {
100
- promise = new Promise ( ( _resolve ) => resolve = _resolve )
101
-
102
- awaitBlocking ( )
103
- await promise
104
- clearTimeout ( timeout )
105
- blockingModules . clear ( )
106
-
107
- debug ( 'writing styles' )
108
- await writeStyles ( files )
109
-
110
- if ( server && needsTouch ) {
111
- const cacheFile = normalizeVitePath ( cacheDir ( 'styles.scss' ) )
112
- server . moduleGraph . getModulesByFile ( cacheFile ) ?. forEach ( module => {
113
- module . importers . forEach ( module => {
114
- if ( module . file ) {
115
- const now = new Date ( )
116
- debug ( `touching ${ module . file } ` )
117
- utimes ( module . file , now , now )
118
- }
119
- } )
120
- } )
121
- needsTouch = false
122
- }
123
- promise = null
124
- }
125
-
126
- return promise
127
- }
128
14
129
15
let configFile : string
130
16
const tempFiles = new Map < string , string > ( )
131
17
132
18
return {
133
19
name : 'vuetify:styles' ,
134
20
enforce : 'pre' ,
135
- configureServer ( _server ) {
136
- server = _server
137
- } ,
138
- buildStart ( ) {
139
- if ( ! server ) {
140
- context = this
141
- }
142
- } ,
143
21
configResolved ( config ) {
144
22
if ( typeof options . styles === 'object' ) {
145
23
if ( path . isAbsolute ( options . styles . configFile ) ) {
@@ -162,23 +40,6 @@ export function stylesPlugin (options: Options): Plugin {
162
40
} else if ( options . styles === 'sass' ) {
163
41
const target = source . replace ( / \. c s s $ / , '.sass' )
164
42
return this . resolve ( target , importer , { skipSelf : true , custom } )
165
- } else if ( options . styles === 'expose' ) {
166
- awaitResolve ( )
167
-
168
- const resolution = await this . resolve (
169
- source . replace ( / \. c s s $ / , '.sass' ) ,
170
- importer ,
171
- { skipSelf : true , custom }
172
- )
173
-
174
- if ( resolution ) {
175
- if ( ! files . has ( resolution . id ) ) {
176
- needsTouch = true
177
- files . add ( resolution . id )
178
- }
179
-
180
- return '\0__void__'
181
- }
182
43
} else if ( typeof options . styles === 'object' ) {
183
44
const resolution = await this . resolve ( source , importer , { skipSelf : true , custom } )
184
45
@@ -200,22 +61,6 @@ export function stylesPlugin (options: Options): Plugin {
200
61
201
62
return null
202
63
} ,
203
- async transform ( code , id ) {
204
- if (
205
- options . styles === 'expose' &&
206
- [ '.scss' , '.sass' ] . some ( v => id . endsWith ( v ) ) &&
207
- styleImportRegexp . test ( code )
208
- ) {
209
- debug ( `awaiting ${ id } ` )
210
- await awaitResolve ( id )
211
- debug ( `returning ${ id } ` )
212
-
213
- return {
214
- code : code . replace ( styleImportRegexp , '$1".cache/vuetify/styles.scss"' ) ,
215
- map : null ,
216
- }
217
- }
218
- } ,
219
64
load ( id ) {
220
65
// When Vite is configured with `optimizeDeps.exclude: ['vuetify']`, the
221
66
// received id contains a version hash (e.g. \0__void__?v=893fa859).
0 commit comments