diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 46db13a0f15f51..3ff50d4e1b2036 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -83,6 +83,7 @@ import { } from '../utils' import type { Logger } from '../logger' import { cleanUrl, isWindows, slash } from '../../shared/utils' +import { NULL_BYTE_PLACEHOLDER } from '../../shared/constants' import { createBackCompatIdResolver } from '../idResolver' import type { ResolveIdFn } from '../idResolver' import { PartialEnvironment } from '../baseEnvironment' @@ -3160,10 +3161,9 @@ async function compileLightningCSS( ): ReturnType { const { config } = environment const deps = new Set() - // Relative path is needed to get stable hash when using CSS modules - const filename = cleanUrl(path.relative(config.root, id)) - const toAbsolute = (filePath: string) => - path.isAbsolute(filePath) ? filePath : path.join(config.root, filePath) + // replace null byte as lightningcss treats that as a string terminator + // https://github.com/parcel-bundler/lightningcss/issues/874 + const filename = id.replace('\0', NULL_BYTE_PLACEHOLDER) let res: LightningCssTransformAttributeResult | LightningCssTransformResult try { @@ -3180,16 +3180,14 @@ async function compileLightningCSS( ).bundleAsync({ ...config.css.lightningcss, filename, + // projectRoot is needed to get stable hash when using CSS modules + projectRoot: config.root, resolver: { read(filePath) { if (filePath === filename) { return src } - // This happens with html-proxy (#13776) - if (!filePath.endsWith('.css')) { - return src - } - return fs.readFileSync(toAbsolute(filePath), 'utf-8') + return fs.readFileSync(filePath, 'utf-8') }, async resolve(id, from) { const publicFile = checkPublicFile( @@ -3202,7 +3200,7 @@ async function compileLightningCSS( const resolved = await getAtImportResolvers( environment.getTopLevelConfig(), - ).css(environment, id, toAbsolute(from)) + ).css(environment, id, from) if (resolved) { deps.add(resolved) @@ -3224,7 +3222,7 @@ async function compileLightningCSS( } catch (e) { e.message = `[lightningcss] ${e.message}` e.loc = { - file: toAbsolute(e.fileName), + file: e.fileName.replace(NULL_BYTE_PLACEHOLDER, '\0'), line: e.loc.line, column: e.loc.column - 1, // 1-based } @@ -3242,7 +3240,10 @@ async function compileLightningCSS( if (skipUrlReplacer(dep.url)) { replaceUrl = dep.url } else if (urlReplacer) { - replaceUrl = await urlReplacer(dep.url, toAbsolute(dep.loc.filePath)) + replaceUrl = await urlReplacer( + dep.url, + dep.loc.filePath.replace(NULL_BYTE_PLACEHOLDER, '\0'), + ) } else { replaceUrl = dep.url } diff --git a/playground/css-lightningcss/__tests__/css-lightningcss.spec.ts b/playground/css-lightningcss/__tests__/css-lightningcss.spec.ts index 538b93a7ebdacb..9dec9ebd992f68 100644 --- a/playground/css-lightningcss/__tests__/css-lightningcss.spec.ts +++ b/playground/css-lightningcss/__tests__/css-lightningcss.spec.ts @@ -61,7 +61,7 @@ test('css modules', async () => { test('inline css modules', async () => { const css = await page.textContent('.modules-inline') - expect(css).toMatch(/\.\w{6}_apply-color-inline/) + expect(css).toMatch(/\._?\w{6}_apply-color-inline/) }) test.runIf(isBuild)('minify css', async () => {