diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index 3af635a5111c71..0277a6594a3445 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -1499,6 +1499,42 @@ function loadPreprocessor( } } +// in unix, scss might append `location.href` in environments that shim `location` +// see https://github.com/sass/dart-sass/issues/710 +function cleanScssBugUrl(url: string) { + if ( + // check bug via `window` and `location` global + typeof window !== 'undefined' && + typeof location !== 'undefined' + ) { + const prefix = location.href.replace(/\/$/, '') + return url.replace(prefix, '') + } else { + return url + } +} + +function fixScssBugImportValue( + data: Sass.ImporterReturnType +): Sass.ImporterReturnType { + // the scss bug doesn't load files properly so we have to load it ourselves + // to prevent internal error when it loads itself + if ( + // check bug via `window` and `location` global + typeof window !== 'undefined' && + typeof location !== 'undefined' && + data && + // @ts-expect-error + data.file && + // @ts-expect-error + data.contents == null + ) { + // @ts-expect-error + data.contents = fs.readFileSync(data.file, 'utf-8') + } + return data +} + // .scss/.sass processor const scss: SassStylePreprocessor = async ( source, @@ -1507,11 +1543,14 @@ const scss: SassStylePreprocessor = async ( resolvers ) => { const render = loadPreprocessor(PreprocessLang.sass, root).render + // NOTE: `sass` always runs it's own importer first, and only falls back to + // the `importer` option when it can't resolve a path const internalImporter: Sass.Importer = (url, importer, done) => { + importer = cleanScssBugUrl(importer) resolvers.sass(url, importer).then((resolved) => { if (resolved) { rebaseUrls(resolved, options.filename, options.alias, '$') - .then((data) => done?.(data)) + .then((data) => done?.(fixScssBugImportValue(data))) .catch((data) => done?.(data)) } else { done?.(null) @@ -1556,7 +1595,7 @@ const scss: SassStylePreprocessor = async ( } }) }) - const deps = result.stats.includedFiles + const deps = result.stats.includedFiles.map((f) => cleanScssBugUrl(f)) const map: ExistingRawSourceMap | undefined = result.map ? JSON.parse(result.map.toString()) : undefined diff --git a/playground/css/vite.config.js b/playground/css/vite.config.js index 40ca1a186e58da..2435f7c0772bcd 100644 --- a/playground/css/vite.config.js +++ b/playground/css/vite.config.js @@ -1,5 +1,10 @@ const path = require('node:path') +// trigger scss bug: https://github.com/sass/dart-sass/issues/710 +// make sure Vite handles safely +globalThis.window = {} +globalThis.location = new URL('http://localhost/') + /** * @type {import('vite').UserConfig} */