Skip to content

Commit

Permalink
feat(css): deprecate css default export (vitejs#11094)
Browse files Browse the repository at this point in the history
Co-authored-by: Manu MA <manu.mtza@gmail.com>
  • Loading branch information
2 people authored and futurGH committed Feb 26, 2023
1 parent 70e1ab2 commit 13e07db
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 56 deletions.
24 changes: 24 additions & 0 deletions packages/vite/client.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,34 +38,58 @@ declare module '*.module.sss' {

// CSS
declare module '*.css' {
/**
* @deprecated Use `import style from './style.css?inline'` instead.
*/
const css: string
export default css
}
declare module '*.scss' {
/**
* @deprecated Use `import style from './style.scss?inline'` instead.
*/
const css: string
export default css
}
declare module '*.sass' {
/**
* @deprecated Use `import style from './style.sass?inline'` instead.
*/
const css: string
export default css
}
declare module '*.less' {
/**
* @deprecated Use `import style from './style.less?inline'` instead.
*/
const css: string
export default css
}
declare module '*.styl' {
/**
* @deprecated Use `import style from './style.styl?inline'` instead.
*/
const css: string
export default css
}
declare module '*.stylus' {
/**
* @deprecated Use `import style from './style.stylus?inline'` instead.
*/
const css: string
export default css
}
declare module '*.pcss' {
/**
* @deprecated Use `import style from './style.pcss?inline'` instead.
*/
const css: string
export default css
}
declare module '*.sss' {
/**
* @deprecated Use `import style from './style.sss?inline'` instead.
*/
const css: string
export default css
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import { fileURLToPath } from 'node:url'
import { describe, expect, it } from 'vitest'
import { transformGlobImport } from '../../../plugins/importMetaGlob'
import { transformWithEsbuild } from '../../../plugins/esbuild'
import { createLogger } from '../../../logger'

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

describe('fixture', async () => {
const resolveId = (id: string) => id
const root = resolve(__dirname, '..')
const logger = createLogger()

it('transform', async () => {
const id = resolve(__dirname, './fixture-a/index.ts')
Expand All @@ -18,7 +20,9 @@ describe('fixture', async () => {
).code

expect(
(await transformGlobImport(code, id, root, resolveId))?.s.toString()
(
await transformGlobImport(code, id, root, resolveId, logger)
)?.s.toString()
).toMatchSnapshot()
})

Expand All @@ -30,7 +34,13 @@ describe('fixture', async () => {
].join('\n')
expect(
(
await transformGlobImport(code, 'virtual:module', root, resolveId)
await transformGlobImport(
code,
'virtual:module',
root,
resolveId,
logger
)
)?.s.toString()
).toMatchSnapshot()

Expand All @@ -39,7 +49,8 @@ describe('fixture', async () => {
"import.meta.glob('./modules/*.ts')",
'virtual:module',
root,
resolveId
resolveId,
logger
)
expect('no error').toBe('should throw an error')
} catch (err) {
Expand All @@ -56,7 +67,9 @@ describe('fixture', async () => {
).code

expect(
(await transformGlobImport(code, id, root, resolveId, true))?.s.toString()
(
await transformGlobImport(code, id, root, resolveId, logger, true)
)?.s.toString()
).toMatchSnapshot()
})
})
3 changes: 3 additions & 0 deletions packages/vite/src/node/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ export const DEFAULT_CONFIG_FILES = [

export const JS_TYPES_RE = /\.(?:j|t)sx?$|\.mjs$/

export const CSS_LANGS_RE =
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)($|\\?)/

export const OPTIMIZABLE_ENTRY_RE = /\.[cm]?[jt]s$/

export const SPECIAL_QUERY_RE = /[?&](?:worker|sharedworker|raw|url)\b/
Expand Down
23 changes: 13 additions & 10 deletions packages/vite/src/node/optimizer/scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ import type { Loader, OnLoadResult, Plugin } from 'esbuild'
import { build, transform } from 'esbuild'
import colors from 'picocolors'
import type { ResolvedConfig } from '..'
import { JS_TYPES_RE, KNOWN_ASSET_TYPES, SPECIAL_QUERY_RE } from '../constants'
import {
CSS_LANGS_RE,
JS_TYPES_RE,
KNOWN_ASSET_TYPES,
SPECIAL_QUERY_RE
} from '../constants'
import {
cleanUrl,
createDebugger,
Expand Down Expand Up @@ -217,7 +222,8 @@ function esbuildScanPlugin(
transpiledContents,
id,
config.root,
resolve
resolve,
config.logger
)

return result?.s.toString() || transpiledContents
Expand Down Expand Up @@ -430,14 +436,11 @@ function esbuildScanPlugin(
// they are done after the bare import resolve because a package name
// may end with these extensions

// css & json & wasm
build.onResolve(
{
filter:
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss|json|wasm)$/
},
externalUnlessEntry
)
// css
build.onResolve({ filter: CSS_LANGS_RE }, externalUnlessEntry)

// json & wasm
build.onResolve({ filter: /\.(json|json5|wasm)$/ }, externalUnlessEntry)

// known asset types
build.onResolve(
Expand Down
20 changes: 12 additions & 8 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ import { getCodeWithSourcemap, injectSourcesContent } from '../server/sourcemap'
import type { ModuleNode } from '../server/moduleGraph'
import type { ResolveFn, ViteDevServer } from '../'
import { toOutputFilePathInCss } from '../build'
import { CLIENT_PUBLIC_PATH, SPECIAL_QUERY_RE } from '../constants'
import {
CLIENT_PUBLIC_PATH,
CSS_LANGS_RE,
SPECIAL_QUERY_RE
} from '../constants'
import type { ResolvedConfig } from '../config'
import type { Plugin } from '../plugin'
import {
Expand Down Expand Up @@ -102,10 +106,7 @@ export interface CSSModulesOptions {
localsConvention?: 'camelCase' | 'camelCaseOnly' | 'dashes' | 'dashesOnly'
}

const cssLangs = `\\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)($|\\?)`
const cssLangRE = new RegExp(cssLangs)
// eslint-disable-next-line regexp/no-unused-capturing-group
const cssModuleRE = new RegExp(`\\.module${cssLangs}`)
const cssModuleRE = new RegExp(`\\.module${CSS_LANGS_RE.source}`)
const directRequestRE = /(?:\?|&)direct\b/
const htmlProxyRE = /(?:\?|&)html-proxy\b/
const commonjsProxyRE = /\?commonjs-proxy/
Expand Down Expand Up @@ -135,10 +136,13 @@ type CssLang =
| keyof typeof PostCssDialectLang

export const isCSSRequest = (request: string): boolean =>
cssLangRE.test(request)
CSS_LANGS_RE.test(request)

export const isModuleCSSRequest = (request: string): boolean =>
cssModuleRE.test(request)

export const isDirectCSSRequest = (request: string): boolean =>
cssLangRE.test(request) && directRequestRE.test(request)
CSS_LANGS_RE.test(request) && directRequestRE.test(request)

export const isDirectRequest = (request: string): boolean =>
directRequestRE.test(request)
Expand Down Expand Up @@ -773,7 +777,7 @@ async function compileCSS(
// crawl them in order to register watch dependencies.
const needInlineImport = code.includes('@import')
const hasUrl = cssUrlRE.test(code) || cssImageSetRE.test(code)
const lang = id.match(cssLangRE)?.[1] as CssLang | undefined
const lang = id.match(CSS_LANGS_RE)?.[1] as CssLang | undefined
const postcssConfig = await resolvePostcssConfig(config, getCssDialect(lang))

// 1. plain css that needs no processing
Expand Down
49 changes: 40 additions & 9 deletions packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import {
ERR_OUTDATED_OPTIMIZED_DEP,
throwOutdatedRequest
} from './optimizedDeps'
import { isCSSRequest, isDirectCSSRequest } from './css'
import { isCSSRequest, isDirectCSSRequest, isModuleCSSRequest } from './css'
import { browserExternalId } from './resolve'

const isDebug = !!process.env.DEBUG
Expand Down Expand Up @@ -436,6 +436,35 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
str().remove(end + 1, expEnd)
}

if (
!isDynamicImport &&
specifier &&
isCSSRequest(specifier) &&
!isModuleCSSRequest(specifier) &&
!specifier.includes('?') // ignore custom queries
) {
const sourceExp = source.slice(expStart, start)
if (
sourceExp.includes('from') && // check default and named imports
!sourceExp.includes('__vite_glob_') // glob handles deprecation message itself
) {
const newImport =
sourceExp + specifier + `?inline` + source.slice(end, expEnd)
this.warn(
`\n` +
colors.cyan(importerModule.file) +
`\n` +
colors.reset(generateCodeFrame(source, start)) +
`\n` +
colors.yellow(
`Default and named imports from CSS files are deprecated. ` +
`Use the ?inline query instead. ` +
`For example: ${newImport}`
)
)
}
}

// static import or valid string in dynamic import
// If resolvable, let's resolve it
if (specifier) {
Expand Down Expand Up @@ -567,14 +596,16 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
`\n` +
colors.cyan(importerModule.file) +
`\n` +
generateCodeFrame(source, start) +
`\nThe above dynamic import cannot be analyzed by Vite.\n` +
`See ${colors.blue(
`https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations`
)} ` +
`for supported dynamic import formats. ` +
`If this is intended to be left as-is, you can use the ` +
`/* @vite-ignore */ comment inside the import() call to suppress this warning.\n`
colors.reset(generateCodeFrame(source, start)) +
colors.yellow(
`\nThe above dynamic import cannot be analyzed by Vite.\n` +
`See ${colors.blue(
`https://github.com/rollup/plugins/tree/master/packages/dynamic-import-vars#limitations`
)} ` +
`for supported dynamic import formats. ` +
`If this is intended to be left as-is, you can use the ` +
`/* @vite-ignore */ comment inside the import() call to suppress this warning.\n`
)
)
}
}
Expand Down
29 changes: 28 additions & 1 deletion packages/vite/src/node/plugins/importMetaGlob.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isAbsolute, posix } from 'node:path'
import micromatch from 'micromatch'
import colors from 'picocolors'
import { stripLiteral } from 'strip-literal'
import type {
ArrayExpression,
Expand All @@ -21,7 +22,14 @@ import type { Plugin } from '../plugin'
import type { ViteDevServer } from '../server'
import type { ModuleNode } from '../server/moduleGraph'
import type { ResolvedConfig } from '../config'
import { normalizePath, slash, transformStableResult } from '../utils'
import {
generateCodeFrame,
normalizePath,
slash,
transformStableResult
} from '../utils'
import type { Logger } from '../logger'
import { isCSSRequest } from './css'

const { isMatch, scan } = micromatch

Expand Down Expand Up @@ -68,6 +76,7 @@ export function importGlobPlugin(config: ResolvedConfig): Plugin {
id,
config.root,
(im) => this.resolve(im, id).then((i) => i?.id || im),
config.logger,
config.experimental.importGlobRestoreExtension
)
if (result) {
Expand Down Expand Up @@ -318,6 +327,7 @@ export async function transformGlobImport(
id: string,
root: string,
resolveId: IdResolver,
logger: Logger,
restoreQueryExtension = false
): Promise<TransformGlobImportResult | null> {
id = slash(id)
Expand Down Expand Up @@ -374,6 +384,23 @@ export async function transformGlobImport(

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

if (
!query.match(/(?:\?|&)inline\b/) &&
files.some((file) => isCSSRequest(file))
) {
logger.warn(
`\n` +
colors.cyan(id) +
`\n` +
colors.reset(generateCodeFrame(code, start)) +
`\n` +
colors.yellow(
`Globbing CSS files without the ?inline query is deprecated. ` +
`Add the \`{ query: '?inline' }\` glob option to fix this.`
)
)
}

const resolvePaths = (file: string) => {
if (!dir) {
if (isRelative)
Expand Down
9 changes: 6 additions & 3 deletions packages/vite/src/node/plugins/splitVendorChunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,13 @@ import type { UserConfig } from '../../node'
import type { Plugin } from '../plugin'

// This file will be built for both ESM and CJS. Avoid relying on other modules as possible.
const cssLangs = `\\.(?:css|less|sass|scss|styl|stylus|pcss|postcss)(?:$|\\?)`
const cssLangRE = new RegExp(cssLangs)

// copy from constants.ts
const CSS_LANGS_RE =
// eslint-disable-next-line regexp/no-unused-capturing-group
/\.(css|less|sass|scss|styl|stylus|pcss|postcss|sss)(?:$|\\?)/
export const isCSSRequest = (request: string): boolean =>
cssLangRE.test(request)
CSS_LANGS_RE.test(request)

// Use splitVendorChunkPlugin() to get the same manualChunks strategy as Vite 2.7
// We don't recommend using this strategy as a general solution moving forward
Expand Down
12 changes: 7 additions & 5 deletions playground/css/__tests__/css.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,18 @@ import {
// note: tests should retrieve the element at the beginning of test and reuse it
// in later assertions to ensure CSS HMR doesn't reload the page
test('imported css', async () => {
const glob = await page.textContent('.imported-css-glob')
expect(glob).toContain('.dir-import')
const globEager = await page.textContent('.imported-css-globEager')
expect(globEager).toContain('.dir-import')
})

test('inline imported css', async () => {
const css = await page.textContent('.imported-css')
expect(css).toMatch(/\.imported ?\{/)
if (isBuild) {
expect(css.trim()).not.toContain('\n') // check minified
}

const glob = await page.textContent('.imported-css-glob')
expect(glob).toContain('.dir-import')
const globEager = await page.textContent('.imported-css-globEager')
expect(globEager).toContain('.dir-import')
})

test('linked css', async () => {
Expand Down
Loading

0 comments on commit 13e07db

Please sign in to comment.