Skip to content

Commit c43dc80

Browse files
committed
feat: remove styles: 'expose'
BREAKING CHANGE: Removed `styles: 'expose'` option
1 parent c4ead73 commit c43dc80

File tree

5 files changed

+7
-280
lines changed

5 files changed

+7
-280
lines changed

packages/shared/src/index.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ import * as path from 'upath'
22

33
export interface Options {
44
autoImport?: importPluginOptions,
5-
styles?: true | 'none' | 'expose' | 'sass' | {
5+
styles?: true | 'none' | 'sass' | {
66
configFile: string,
77
},
8-
/** @internal Only for testing */
9-
stylesTimeout?: number
108
}
119

1210
export type importPluginOptions =

packages/vite-plugin/src/index.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,14 @@ function vuetify (_options: Options = {}): Plugin[] {
88
const options: Options = {
99
autoImport: true,
1010
styles: true,
11-
stylesTimeout: 1000,
1211
..._options,
1312
}
1413

1514
const plugins: Plugin[] = []
1615
if (options.autoImport) {
1716
plugins.push(importPlugin())
1817
}
19-
if (includes(['none', 'expose', 'sass'], options.styles) || isObject(options.styles)) {
18+
if (includes(['none', 'sass'], options.styles) || isObject(options.styles)) {
2019
plugins.push(stylesPlugin(options))
2120
}
2221

packages/vite-plugin/src/stylesPlugin.ts

Lines changed: 2 additions & 157 deletions
Original file line numberDiff line numberDiff line change
@@ -1,145 +1,23 @@
1-
import { utimes } from 'fs/promises'
21
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'
63

7-
import type { Plugin, ViteDevServer } from 'vite'
4+
import type { Plugin } from 'vite'
85
import type { Options } from '@vuetify/loader-shared'
9-
import type { PluginContext } from 'rollup'
10-
11-
const debug = _debug('vuetify:styles')
126

137
function isSubdir (root: string, test: string) {
148
const relative = path.relative(root, test)
159
return relative && !relative.startsWith('..') && !path.isAbsolute(relative)
1610
}
1711

18-
const styleImportRegexp = /(@use |meta\.load-css\()['"](vuetify(?:\/lib)?(?:\/styles(?:\/main(?:\.sass)?)?)?)['"]/
19-
2012
export function stylesPlugin (options: Options): Plugin {
2113
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[ac]|c)ss/.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[ac]|c)ss/.test(k) && // Ignore stylesheets
56-
!blockingModules.has(v.id!) && // Ignore the current file
57-
!/\/node_modules\/\.vite\/deps\/(?!vuetify[._])/.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-
}
12814

12915
let configFile: string
13016
const tempFiles = new Map<string, string>()
13117

13218
return {
13319
name: 'vuetify:styles',
13420
enforce: 'pre',
135-
configureServer (_server) {
136-
server = _server
137-
},
138-
buildStart () {
139-
if (!server) {
140-
context = this
141-
}
142-
},
14321
configResolved (config) {
14422
if (typeof options.styles === 'object') {
14523
if (path.isAbsolute(options.styles.configFile)) {
@@ -162,23 +40,6 @@ export function stylesPlugin (options: Options): Plugin {
16240
} else if (options.styles === 'sass') {
16341
const target = source.replace(/\.css$/, '.sass')
16442
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(/\.css$/, '.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-
}
18243
} else if (typeof options.styles === 'object') {
18344
const resolution = await this.resolve(source, importer, { skipSelf: true, custom })
18445

@@ -200,22 +61,6 @@ export function stylesPlugin (options: Options): Plugin {
20061

20162
return null
20263
},
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-
},
21964
load (id) {
22065
// When Vite is configured with `optimizeDeps.exclude: ['vuetify']`, the
22166
// received id contains a version hash (e.g. \0__void__?v=893fa859).

packages/webpack-plugin/src/plugin.ts

Lines changed: 3 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,13 @@ import * as mkdirp from 'mkdirp'
66

77
import {
88
resolveVuetifyBase,
9-
writeStyles,
10-
includes,
119
isObject,
1210
cacheDir,
1311
transformAssetUrls,
1412
normalizePath,
1513
} from '@vuetify/loader-shared'
1614

17-
import type { Compiler, NormalModule, Module } from 'webpack'
15+
import type { Compiler } from 'webpack'
1816
import type { Options } from '@vuetify/loader-shared'
1917

2018
function isSubdir (root: string, test: string) {
@@ -29,7 +27,6 @@ export class VuetifyPlugin {
2927
this.options = {
3028
autoImport: true,
3129
styles: true,
32-
stylesTimeout: 10000,
3330
...options,
3431
}
3532
}
@@ -75,7 +72,7 @@ export class VuetifyPlugin {
7572
})
7673
}
7774

78-
if (includes(['none', 'expose'], this.options.styles)) {
75+
if (this.options.styles === 'none') {
7976
compiler.options.module.rules.push({
8077
enforce: 'pre',
8178
test: /\.css$/,
@@ -87,103 +84,7 @@ export class VuetifyPlugin {
8784
hookResolve(file => file.replace(/\.css$/, '.sass'))
8885
}
8986

90-
if (this.options.styles === 'expose') {
91-
const files = new Set<string>()
92-
let resolve: (v: boolean) => void
93-
let promise: Promise<boolean> | null
94-
let timeout: NodeJS.Timeout
95-
96-
const blockingModules = new Set<string>()
97-
const pendingModules = new Map<string, Module>()
98-
compiler.hooks.compilation.tap('vuetify-loader', (compilation) => {
99-
compilation.hooks.buildModule.tap('vuetify-loader', (module) => {
100-
pendingModules.set((module as NormalModule).request, module)
101-
})
102-
compilation.hooks.succeedModule.tap('vuetify-loader', (module) => {
103-
pendingModules.delete((module as NormalModule).request)
104-
if (
105-
resolve &&
106-
!Array.from(pendingModules.keys()).filter(k => !blockingModules.has(k)).length
107-
) {
108-
resolve(false)
109-
}
110-
})
111-
})
112-
113-
const logger = compiler.getInfrastructureLogger('vuetify-loader')
114-
const awaitResolve = async (id?: string) => {
115-
if (id) {
116-
blockingModules.add(id)
117-
}
118-
119-
if (!promise) {
120-
promise = new Promise((_resolve) => resolve = _resolve)
121-
122-
clearTimeout(timeout)
123-
timeout = setTimeout(() => {
124-
logger.error('styles fallback timeout hit', {
125-
blockingModules: Array.from(blockingModules.values()),
126-
pendingModules: Array.from(pendingModules.values(), module => (module as NormalModule).resource),
127-
})
128-
resolve(false)
129-
}, this.options.stylesTimeout)
130-
131-
if (!Array.from(pendingModules.keys()).filter(k => !blockingModules.has(k)).length) {
132-
resolve(false)
133-
}
134-
135-
const start = files.size
136-
await promise
137-
clearTimeout(timeout)
138-
blockingModules.clear()
139-
140-
if (files.size > start) {
141-
await writeStyles(files)
142-
}
143-
promise = null
144-
}
145-
146-
return promise
147-
}
148-
149-
compiler.options.module.rules.push({
150-
enforce: 'pre',
151-
test: /\.s[ac]ss$/,
152-
loader: require.resolve('./styleLoader'),
153-
options: { awaitResolve },
154-
})
155-
156-
compiler.options.resolve.plugins = compiler.options.resolve.plugins || []
157-
compiler.options.resolve.plugins.push({
158-
apply (resolver) {
159-
resolver
160-
.getHook('resolve')
161-
.tapAsync('vuetify-loader', async (request, context, callback) => {
162-
if (!(
163-
request.path &&
164-
request.request?.endsWith('.css') &&
165-
isSubdir(vuetifyBase, request.path)
166-
)) {
167-
return callback()
168-
}
169-
170-
resolver.resolve(
171-
{},
172-
request.path,
173-
request.request.replace(/\.css$/, '.sass'),
174-
context,
175-
(err, resolution) => {
176-
if (resolution && !files.has(resolution)) {
177-
awaitResolve()
178-
files.add(resolution)
179-
}
180-
return callback()
181-
}
182-
)
183-
})
184-
}
185-
})
186-
} else if (isObject(this.options.styles)) {
87+
if (isObject(this.options.styles)) {
18788
const configFile = path.isAbsolute(this.options.styles.configFile)
18889
? this.options.styles.configFile
18990
: path.join(

packages/webpack-plugin/src/styleLoader.ts

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)