Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(css)!: remove css default export #14125

Merged
merged 7 commits into from Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/guide/features.md
Expand Up @@ -182,7 +182,7 @@ export default defineConfig({

## CSS

Importing `.css` files will inject its content to the page via a `<style>` tag with HMR support. You can also retrieve the processed CSS as a string as the module's default export.
Importing `.css` files will inject its content to the page via a `<style>` tag with HMR support.

### `@import` Inlining and Rebasing

Expand Down Expand Up @@ -257,7 +257,7 @@ import otherStyles from './bar.css?inline' // will not be injected
```

::: tip NOTE
Default and named imports from CSS files (e.g `import style from './foo.css'`) are deprecated since Vite 4. Use the `?inline` query instead.
Default and named imports from CSS files (e.g `import style from './foo.css'`) are removed since Vite 5. Use the `?inline` query instead.
:::

### Lightning CSS
Expand Down
64 changes: 8 additions & 56 deletions packages/vite/client.d.ts
Expand Up @@ -37,62 +37,14 @@ 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
}
declare module '*.css' {}
declare module '*.scss' {}
declare module '*.sass' {}
declare module '*.less' {}
declare module '*.styl' {}
declare module '*.stylus' {}
declare module '*.pcss' {}
declare module '*.sss' {}

// Built-in asset types
// see `src/node/constants.ts`
Expand Down
Expand Up @@ -18,17 +18,13 @@ describe('fixture', async () => {
).code

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

it('preserve line count', async () => {
const getTransformedLineCount = async (code: string) =>
(
await transformGlobImport(code, 'virtual:module', root, resolveId, true)
)?.s
(await transformGlobImport(code, 'virtual:module', root, resolveId))?.s
.toString()
.split('\n').length

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

Expand All @@ -62,7 +58,6 @@ describe('fixture', async () => {
'virtual:module',
root,
resolveId,
true,
)
expect('no error').toBe('should throw an error')
} catch (err) {
Expand All @@ -80,7 +75,7 @@ describe('fixture', async () => {

expect(
(
await transformGlobImport(code, id, root, resolveId, true, true)
await transformGlobImport(code, id, root, resolveId, true)
)?.s.toString(),
).toMatchSnapshot()
})
Expand Down
1 change: 0 additions & 1 deletion packages/vite/src/node/optimizer/scan.ts
Expand Up @@ -327,7 +327,6 @@ function esbuildScanPlugin(
id,
config.root,
resolve,
config.isProduction,
)

return result?.s.toString() || transpiledContents
Expand Down
29 changes: 10 additions & 19 deletions packages/vite/src/node/plugins/css.ts
Expand Up @@ -164,7 +164,6 @@ const commonjsProxyRE = /\?commonjs-proxy/
const inlineRE = /[?&]inline\b/
const inlineCSSRE = /[?&]inline-css\b/
const styleAttrRE = /[?&]style-attr\b/
const usedRE = /[?&]used\b/
const varRE = /^var\(/i

const cssBundleName = 'style.css'
Expand Down Expand Up @@ -467,10 +466,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
`const __vite__css = ${JSON.stringify(cssContent)}`,
`__vite__updateStyle(__vite__id, __vite__css)`,
// css modules exports change on edit so it can't self accept
`${
modulesCode ||
`import.meta.hot.accept()\nexport default __vite__css`
}`,
`${modulesCode || 'import.meta.hot.accept()'}`,
`import.meta.hot.prune(() => __vite__removeStyle(__vite__id))`,
].join('\n')
return { code, map: { mappings: '' } }
Expand Down Expand Up @@ -499,22 +495,17 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
}

let code: string
if (usedRE.test(id)) {
if (modulesCode) {
code = modulesCode
} else {
let content = css
if (config.build.cssMinify) {
content = await minifyCSS(content, config, true)
}
code = `export default ${JSON.stringify(content)}`
if (modulesCode) {
code = modulesCode
} else if (inlined) {
let content = css
if (config.build.cssMinify) {
content = await minifyCSS(content, config, true)
}
code = `export default ${JSON.stringify(content)}`
} else {
// if moduleCode exists return it **even if** it does not have `?used`
// this will disable tree-shake to work with `import './foo.module.css'` but this usually does not happen
// this is a limitation of the current approach by `?used` to make tree-shake work
// See #8936 for more details
code = modulesCode || `export default ''`
// empty module when it's not a CSS module nor `?inline`
code = ''
}

return {
Expand Down
31 changes: 1 addition & 30 deletions packages/vite/src/node/plugins/importAnalysis.ts
Expand Up @@ -61,7 +61,7 @@ import {
ERR_OUTDATED_OPTIMIZED_DEP,
throwOutdatedRequest,
} from './optimizedDeps'
import { isCSSRequest, isDirectCSSRequest, isModuleCSSRequest } from './css'
import { isCSSRequest, isDirectCSSRequest } from './css'
import { browserExternalId } from './resolve'

const debug = createDebugger('vite:import-analysis')
Expand Down Expand Up @@ -528,35 +528,6 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
// normalize
const [url, resolvedId] = await normalizeUrl(specifier, start)

if (
!isDynamicImport &&
specifier &&
!specifier.includes('?') && // ignore custom queries
isCSSRequest(resolvedId) &&
!isModuleCSSRequest(resolvedId)
) {
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}`,
),
)
}
}

// record as safe modules
// safeModulesPath should not include the base prefix.
// See https://github.com/vitejs/vite/issues/9438#issuecomment-1465270409
Expand Down
25 changes: 1 addition & 24 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Expand Up @@ -7,7 +7,6 @@ import colors from 'picocolors'
import type { RawSourceMap } from '@ampproject/remapping'
import convertSourceMap from 'convert-source-map'
import {
bareImportRE,
cleanUrl,
combineSourcemaps,
generateCodeFrame,
Expand All @@ -24,8 +23,7 @@ import type { ResolvedConfig } from '../config'
import { toOutputFilePathInJS } from '../build'
import { genSourceMapUrl } from '../server/sourcemap'
import { getDepsOptimizer, optimizedDepNeedsInterop } from '../optimizer'
import { SPECIAL_QUERY_RE } from '../constants'
import { isCSSRequest, removedPureCssFilesCache } from './css'
import { removedPureCssFilesCache } from './css'
import { interopNamedImports } from './importAnalysis'

/**
Expand Down Expand Up @@ -380,27 +378,6 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin {
}
}
}

// Differentiate CSS imports that use the default export from those that
// do not by injecting a ?used query - this allows us to avoid including
// the CSS string when unnecessary (esbuild has trouble tree-shaking
// them)
if (
specifier &&
isCSSRequest(specifier) &&
// always inject ?used query when it is a dynamic import
// because there is no way to check whether the default export is used
(source.slice(expStart, start).includes('from') || isDynamicImport) &&
// already has ?used query (by import.meta.glob)
!specifier.match(/\?used(&|$)/) &&
// don't append ?used when SPECIAL_QUERY_RE exists
!specifier.match(SPECIAL_QUERY_RE) &&
// edge case for package names ending with .css (e.g normalize.css)
!(bareImportRE.test(specifier) && !specifier.includes('/'))
) {
const url = specifier.replace(/\?|$/, (m) => `?used${m ? '&' : ''}`)
str().update(start, end, isDynamicImport ? `'${url}'` : url)
}
}

if (
Expand Down