Skip to content

Commit 97f8b4d

Browse files
authoredNov 30, 2022
fix(importGlob): don't warn when CSS default import is not used (#11121)
1 parent 1db52bf commit 97f8b4d

File tree

8 files changed

+112
-103
lines changed

8 files changed

+112
-103
lines changed
 

‎packages/vite/src/node/__tests__/plugins/importGlob/fixture-c/a.css

-3
This file was deleted.

‎packages/vite/src/node/__tests__/plugins/importGlob/fixture-c/b.css

-3
This file was deleted.

‎packages/vite/src/node/__tests__/plugins/importGlob/fixture-c/c.module.css

-3
This file was deleted.

‎packages/vite/src/node/__tests__/plugins/importGlob/fixture.test.ts

+5-61
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,12 @@ import { fileURLToPath } from 'node:url'
44
import { describe, expect, it } from 'vitest'
55
import { transformGlobImport } from '../../../plugins/importMetaGlob'
66
import { transformWithEsbuild } from '../../../plugins/esbuild'
7-
import type { Logger } from '../../../logger'
8-
import { createLogger } from '../../../logger'
97

108
const __dirname = resolve(fileURLToPath(import.meta.url), '..')
119

1210
describe('fixture', async () => {
1311
const resolveId = (id: string) => id
1412
const root = resolve(__dirname, '..')
15-
const logger = createLogger()
1613

1714
it('transform', async () => {
1815
const id = resolve(__dirname, './fixture-a/index.ts')
@@ -21,22 +18,14 @@ describe('fixture', async () => {
2118
).code
2219

2320
expect(
24-
(
25-
await transformGlobImport(code, id, root, resolveId, logger)
26-
)?.s.toString()
21+
(await transformGlobImport(code, id, root, resolveId, true))?.s.toString()
2722
).toMatchSnapshot()
2823
})
2924

3025
it('preserve line count', async () => {
3126
const getTransformedLineCount = async (code: string) =>
3227
(
33-
await transformGlobImport(
34-
code,
35-
'virtual:module',
36-
root,
37-
resolveId,
38-
logger
39-
)
28+
await transformGlobImport(code, 'virtual:module', root, resolveId, true)
4029
)?.s
4130
.toString()
4231
.split('\n').length
@@ -61,13 +50,7 @@ describe('fixture', async () => {
6150
].join('\n')
6251
expect(
6352
(
64-
await transformGlobImport(
65-
code,
66-
'virtual:module',
67-
root,
68-
resolveId,
69-
logger
70-
)
53+
await transformGlobImport(code, 'virtual:module', root, resolveId, true)
7154
)?.s.toString()
7255
).toMatchSnapshot()
7356

@@ -77,7 +60,7 @@ describe('fixture', async () => {
7760
'virtual:module',
7861
root,
7962
resolveId,
80-
logger
63+
true
8164
)
8265
expect('no error').toBe('should throw an error')
8366
} catch (err) {
@@ -95,47 +78,8 @@ describe('fixture', async () => {
9578

9679
expect(
9780
(
98-
await transformGlobImport(code, id, root, resolveId, logger, true)
81+
await transformGlobImport(code, id, root, resolveId, true, true)
9982
)?.s.toString()
10083
).toMatchSnapshot()
10184
})
102-
103-
it('warn when glob css without ?inline', async () => {
104-
const logs: string[] = []
105-
const logger = {
106-
warn(msg: string) {
107-
logs.push(msg)
108-
}
109-
} as Logger
110-
111-
await transformGlobImport(
112-
"import.meta.glob('./fixture-c/*.css', { query: '?inline' })",
113-
fileURLToPath(import.meta.url),
114-
root,
115-
resolveId,
116-
logger
117-
)
118-
expect(logs).toHaveLength(0)
119-
120-
await transformGlobImport(
121-
"import.meta.glob('./fixture-c/*.module.css')",
122-
fileURLToPath(import.meta.url),
123-
root,
124-
resolveId,
125-
logger
126-
)
127-
expect(logs).toHaveLength(0)
128-
129-
await transformGlobImport(
130-
"import.meta.glob('./fixture-c/*.css')",
131-
fileURLToPath(import.meta.url),
132-
root,
133-
resolveId,
134-
logger
135-
)
136-
expect(logs).toHaveLength(1)
137-
expect(logs[0]).to.include(
138-
'Globbing CSS files without the ?inline query is deprecated'
139-
)
140-
})
14185
})

‎packages/vite/src/node/optimizer/scan.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ function esbuildScanPlugin(
223223
id,
224224
config.root,
225225
resolve,
226-
config.logger
226+
config.isProduction
227227
)
228228

229229
return result?.s.toString() || transpiledContents

‎packages/vite/src/node/plugins/importMetaGlob.ts

+75-32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { isAbsolute, posix } from 'node:path'
22
import micromatch from 'micromatch'
3-
import colors from 'picocolors'
43
import { stripLiteral } from 'strip-literal'
54
import type {
65
ArrayExpression,
@@ -26,12 +25,10 @@ import type { ModuleNode } from '../server/moduleGraph'
2625
import type { ResolvedConfig } from '../config'
2726
import {
2827
evalValue,
29-
generateCodeFrame,
3028
normalizePath,
3129
slash,
3230
transformStableResult
3331
} from '../utils'
34-
import type { Logger } from '../logger'
3532
import { isCSSRequest, isModuleCSSRequest } from './css'
3633

3734
const { isMatch, scan } = micromatch
@@ -79,7 +76,7 @@ export function importGlobPlugin(config: ResolvedConfig): Plugin {
7976
id,
8077
config.root,
8178
(im) => this.resolve(im, id).then((i) => i?.id || im),
82-
config.logger,
79+
config.isProduction,
8380
config.experimental.importGlobRestoreExtension
8481
)
8582
if (result) {
@@ -320,6 +317,24 @@ const importPrefix = '__vite_glob_'
320317

321318
const { basename, dirname, relative, join } = posix
322319

320+
const warnedCSSDefaultImportVarName = '__vite_warned_css_default_import'
321+
const jsonStringifyInOneline = (input: any) =>
322+
JSON.stringify(input).replace(/[{,:]/g, '$& ').replace(/\}/g, ' }')
323+
const createCssDefaultImportWarning = (
324+
globs: string[],
325+
options: GeneralImportGlobOptions
326+
) =>
327+
`if (!${warnedCSSDefaultImportVarName}) {` +
328+
`${warnedCSSDefaultImportVarName} = true;` +
329+
`console.warn(${JSON.stringify(
330+
'Default import of CSS without `?inline` is deprecated. ' +
331+
"Add the `{ query: '?inline' }` glob option to fix this.\n" +
332+
`For example: \`import.meta.glob(${jsonStringifyInOneline(
333+
globs.length === 1 ? globs[0] : globs
334+
)}, ${jsonStringifyInOneline({ ...options, query: '?inline' })})\``
335+
)});` +
336+
`}`
337+
323338
export interface TransformGlobImportResult {
324339
s: MagicString
325340
matches: ParsedImportGlob[]
@@ -334,7 +349,7 @@ export async function transformGlobImport(
334349
id: string,
335350
root: string,
336351
resolveId: IdResolver,
337-
logger: Logger,
352+
isProduction: boolean,
338353
restoreQueryExtension = false
339354
): Promise<TransformGlobImportResult | null> {
340355
id = slash(id)
@@ -365,7 +380,15 @@ export async function transformGlobImport(
365380
const staticImports = (
366381
await Promise.all(
367382
matches.map(
368-
async ({ globsResolved, isRelative, options, index, start, end }) => {
383+
async ({
384+
globs,
385+
globsResolved,
386+
isRelative,
387+
options,
388+
index,
389+
start,
390+
end
391+
}) => {
369392
const cwd = getCommonBase(globsResolved) ?? root
370393
const files = (
371394
await fg(globsResolved, {
@@ -391,25 +414,6 @@ export async function transformGlobImport(
391414

392415
if (query && !query.startsWith('?')) query = `?${query}`
393416

394-
if (
395-
!query && // ignore custom queries
396-
files.some(
397-
(file) => isCSSRequest(file) && !isModuleCSSRequest(file)
398-
)
399-
) {
400-
logger.warn(
401-
`\n` +
402-
colors.cyan(id) +
403-
`\n` +
404-
colors.reset(generateCodeFrame(code, start)) +
405-
`\n` +
406-
colors.yellow(
407-
`Globbing CSS files without the ?inline query is deprecated. ` +
408-
`Add the \`{ query: '?inline' }\` glob option to fix this.`
409-
)
410-
)
411-
}
412-
413417
const resolvePaths = (file: string) => {
414418
if (!dir) {
415419
if (isRelative)
@@ -434,6 +438,7 @@ export async function transformGlobImport(
434438
return { filePath, importPath }
435439
}
436440

441+
let includesCSS = false
437442
files.forEach((file, i) => {
438443
const paths = resolvePaths(file)
439444
const filePath = paths.filePath
@@ -448,6 +453,10 @@ export async function transformGlobImport(
448453

449454
importPath = `${importPath}${importQuery}`
450455

456+
const isCSS =
457+
!query && isCSSRequest(file) && !isModuleCSSRequest(file)
458+
includesCSS ||= isCSS
459+
451460
const importKey =
452461
options.import && options.import !== '*'
453462
? options.import
@@ -461,14 +470,36 @@ export async function transformGlobImport(
461470
staticImports.push(
462471
`import ${expression} from ${JSON.stringify(importPath)}`
463472
)
464-
objectProps.push(`${JSON.stringify(filePath)}: ${variableName}`)
473+
if (!isProduction && isCSS) {
474+
objectProps.push(
475+
`get ${JSON.stringify(
476+
filePath
477+
)}() { ${createCssDefaultImportWarning(
478+
globs,
479+
options
480+
)} return ${variableName} }`
481+
)
482+
} else {
483+
objectProps.push(`${JSON.stringify(filePath)}: ${variableName}`)
484+
}
465485
} else {
466486
let importStatement = `import(${JSON.stringify(importPath)})`
467487
if (importKey)
468488
importStatement += `.then(m => m[${JSON.stringify(importKey)}])`
469-
objectProps.push(
470-
`${JSON.stringify(filePath)}: () => ${importStatement}`
471-
)
489+
if (!isProduction && isCSS) {
490+
objectProps.push(
491+
`${JSON.stringify(
492+
filePath
493+
)}: () => { ${createCssDefaultImportWarning(
494+
globs,
495+
options
496+
)} return ${importStatement}}`
497+
)
498+
} else {
499+
objectProps.push(
500+
`${JSON.stringify(filePath)}: () => ${importStatement}`
501+
)
502+
}
472503
}
473504
})
474505

@@ -480,9 +511,21 @@ export async function transformGlobImport(
480511
originalLineBreakCount > 0
481512
? '\n'.repeat(originalLineBreakCount)
482513
: ''
483-
const replacement = `/* #__PURE__ */ Object.assign({${objectProps.join(
484-
','
485-
)}${lineBreaks}})`
514+
515+
let replacement: string
516+
if (!isProduction && includesCSS) {
517+
replacement =
518+
'/* #__PURE__ */ Object.assign(' +
519+
'(() => {' +
520+
`let ${warnedCSSDefaultImportVarName} = false;` +
521+
`return {${objectProps.join(',')}${lineBreaks}};` +
522+
'})()' +
523+
')'
524+
} else {
525+
replacement = `/* #__PURE__ */ Object.assign({${objectProps.join(
526+
','
527+
)}${lineBreaks}})`
528+
}
486529
s.overwrite(start, end, replacement)
487530

488531
return staticImports

‎playground/glob-import/__tests__/glob-import.spec.ts

+27
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@ import {
77
findAssetFile,
88
getColor,
99
isBuild,
10+
isServe,
1011
page,
1112
removeFile,
13+
untilBrowserLogAfter,
14+
viteTestUrl,
1215
withRetry
1316
} from '~utils'
1417

@@ -190,6 +193,30 @@ test('tree-shake eager css', async () => {
190193
}
191194
})
192195

196+
test('warn CSS default import', async () => {
197+
const logs = await untilBrowserLogAfter(
198+
() => page.goto(viteTestUrl),
199+
'Ran scripts'
200+
)
201+
const noTreeshakeCSSMessage =
202+
'For example: `import.meta.glob("/no-tree-shake.css", { "eager": true, "query": "?inline" })`'
203+
const treeshakeCSSMessage =
204+
'For example: `import.meta.glob("/tree-shake.css", { "eager": true, "query": "?inline" })`'
205+
206+
expect(
207+
logs.some((log) => log.includes(noTreeshakeCSSMessage)),
208+
`expected logs to include a message including ${JSON.stringify(
209+
noTreeshakeCSSMessage
210+
)}`
211+
).toBe(isServe)
212+
expect(
213+
logs.every((log) => !log.includes(treeshakeCSSMessage)),
214+
`expected logs not to include a message including ${JSON.stringify(
215+
treeshakeCSSMessage
216+
)}`
217+
).toBe(true)
218+
})
219+
193220
test('escapes special chars in globs without mangling user supplied glob suffix', async () => {
194221
// the escape dir contains subdirectories where each has a name that needs escaping for glob safety
195222
// inside each of them is a glob.js that exports the result of a relative glob `./**/*.js`

‎playground/glob-import/index.html

+4
Original file line numberDiff line numberDiff line change
@@ -140,3 +140,7 @@ <h2>Escape alias glob</h2>
140140
.map(([glob]) => glob)
141141
document.querySelector('.escape-alias').textContent = alias.sort().join('\n')
142142
</script>
143+
144+
<script type="module">
145+
console.log('Ran scripts')
146+
</script>

0 commit comments

Comments
 (0)
Please sign in to comment.