Skip to content

Commit 22e005a

Browse files
sapphi-redmoonlitusun
authored andcommitted
refactor(css)!: remove sass legacy API support (vitejs#19977)
1 parent 077c399 commit 22e005a

File tree

8 files changed

+15
-251
lines changed

8 files changed

+15
-251
lines changed

docs/config/shared-options.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,8 @@ Note if an inline config is provided, Vite will not search for other PostCSS con
227227
Specify options to pass to CSS pre-processors. The file extensions are used as keys for the options. The supported options for each preprocessor can be found in their respective documentation:
228228

229229
- `sass`/`scss`:
230-
- Select the sass API to use with `api: "modern-compiler" | "modern" | "legacy"` (default `"modern-compiler"` if `sass-embedded` is installed, otherwise `"modern"`). For the best performance, it's recommended to use `api: "modern-compiler"` with the `sass-embedded` package. The `"legacy"` API is deprecated and will be removed in Vite 7.
231-
- [Options (modern)](https://sass-lang.com/documentation/js-api/interfaces/stringoptions/)
232-
- [Options (legacy)](https://sass-lang.com/documentation/js-api/interfaces/LegacyStringOptions).
230+
- Select the sass API to use with `api: "modern-compiler" | "modern"` (default `"modern-compiler"` if `sass-embedded` is installed, otherwise `"modern"`). For the best performance, it's recommended to use `api: "modern-compiler"` with the `sass-embedded` package.
231+
- [Options](https://sass-lang.com/documentation/js-api/interfaces/stringoptions/)
233232
- `less`: [Options](https://lesscss.org/usage/#less-options).
234233
- `styl`/`stylus`: Only [`define`](https://stylus-lang.com/docs/js.html#define-name-node) is supported, which can be passed as an object.
235234

@@ -248,7 +247,7 @@ export default defineConfig({
248247
},
249248
},
250249
scss: {
251-
api: 'modern-compiler', // or "modern", "legacy"
250+
api: 'modern-compiler', // or "modern"
252251
importers: [
253252
// ...
254253
],

packages/vite/src/node/plugins/css.ts

Lines changed: 10 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { WorkerWithFallback } from 'artichokie'
3030
import { globSync } from 'tinyglobby'
3131
import type {
3232
LessPreprocessorBaseOptions,
33-
SassLegacyPreprocessBaseOptions,
3433
SassModernPreprocessBaseOptions,
3534
StylusPreprocessorBaseOptions,
3635
} from 'types/internal/cssPreprocessorOptions'
@@ -2252,10 +2251,7 @@ type PreprocessorAdditionalData =
22522251

22532252
export type SassPreprocessorOptions = {
22542253
additionalData?: PreprocessorAdditionalData
2255-
} & (
2256-
| ({ api: 'legacy' } & SassLegacyPreprocessBaseOptions)
2257-
| ({ api?: 'modern' | 'modern-compiler' } & SassModernPreprocessBaseOptions)
2258-
)
2254+
} & ({ api?: 'modern' | 'modern-compiler' } & SassModernPreprocessBaseOptions)
22592255

22602256
export type LessPreprocessorOptions = {
22612257
additionalData?: PreprocessorAdditionalData
@@ -2377,149 +2373,8 @@ function cleanScssBugUrl(url: string) {
23772373
}
23782374
}
23792375

2380-
function fixScssBugImportValue(
2381-
data: Sass.LegacyImporterResult,
2382-
): Sass.LegacyImporterResult {
2383-
// the scss bug doesn't load files properly so we have to load it ourselves
2384-
// to prevent internal error when it loads itself
2385-
if (
2386-
// check bug via `window` and `location` global
2387-
typeof window !== 'undefined' &&
2388-
typeof location !== 'undefined' &&
2389-
data &&
2390-
'file' in data &&
2391-
(!('contents' in data) || data.contents == null)
2392-
) {
2393-
// @ts-expect-error we need to preserve file property for HMR
2394-
data.contents = fs.readFileSync(data.file, 'utf-8')
2395-
}
2396-
return data
2397-
}
2398-
23992376
// #region Sass
24002377
// .scss/.sass processor
2401-
const makeScssWorker = (
2402-
environment: PartialEnvironment,
2403-
resolvers: CSSAtImportResolvers,
2404-
alias: Alias[],
2405-
maxWorkers: number | undefined,
2406-
packageName: 'sass' | 'sass-embedded',
2407-
) => {
2408-
const internalImporter = async (
2409-
url: string,
2410-
importer: string,
2411-
filename: string,
2412-
) => {
2413-
importer = cleanScssBugUrl(importer)
2414-
const resolved = await resolvers.sass(environment, url, importer)
2415-
if (resolved) {
2416-
try {
2417-
const data = await rebaseUrls(
2418-
environment,
2419-
resolved,
2420-
filename,
2421-
alias,
2422-
'$',
2423-
resolvers.sass,
2424-
)
2425-
if (packageName === 'sass-embedded') {
2426-
return data
2427-
}
2428-
return fixScssBugImportValue(data)
2429-
} catch (data) {
2430-
return data
2431-
}
2432-
} else {
2433-
return null
2434-
}
2435-
}
2436-
2437-
const worker = new WorkerWithFallback(
2438-
() =>
2439-
async (
2440-
sassPath: string,
2441-
data: string,
2442-
// additionalData can a function that is not cloneable but it won't be used
2443-
options: SassStylePreprocessorInternalOptions & {
2444-
api: 'legacy'
2445-
additionalData: undefined
2446-
},
2447-
) => {
2448-
// eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker
2449-
const sass: typeof Sass = require(sassPath)
2450-
// eslint-disable-next-line no-restricted-globals
2451-
const path: typeof import('node:path') = require('node:path')
2452-
2453-
// NOTE: `sass` always runs it's own importer first, and only falls back to
2454-
// the `importer` option when it can't resolve a path
2455-
const _internalImporter: Sass.LegacyAsyncImporter = (
2456-
url,
2457-
importer,
2458-
done,
2459-
) => {
2460-
internalImporter(url, importer, options.filename).then((data) =>
2461-
done(data),
2462-
)
2463-
}
2464-
const importer = [_internalImporter]
2465-
if (options.importer) {
2466-
if (Array.isArray(options.importer)) {
2467-
importer.unshift(...options.importer)
2468-
} else {
2469-
importer.unshift(options.importer)
2470-
}
2471-
}
2472-
2473-
const finalOptions: Sass.LegacyOptions<'async'> = {
2474-
// support @import from node dependencies by default
2475-
includePaths: ['node_modules'],
2476-
...options,
2477-
data,
2478-
file: options.filename,
2479-
outFile: options.filename,
2480-
importer,
2481-
...(options.enableSourcemap
2482-
? {
2483-
sourceMap: true,
2484-
omitSourceMapUrl: true,
2485-
sourceMapRoot: path.dirname(options.filename),
2486-
}
2487-
: {}),
2488-
}
2489-
return new Promise<ScssWorkerResult>((resolve, reject) => {
2490-
sass.render(finalOptions, (err, res) => {
2491-
if (err) {
2492-
reject(err)
2493-
} else {
2494-
resolve({
2495-
css: res!.css.toString(),
2496-
map: res!.map?.toString(),
2497-
stats: res!.stats,
2498-
})
2499-
}
2500-
})
2501-
})
2502-
},
2503-
{
2504-
parentFunctions: { internalImporter },
2505-
shouldUseFake(_sassPath, _data, options) {
2506-
// functions and importer is a function and is not serializable
2507-
// in that case, fallback to running in main thread
2508-
return !!(
2509-
(options.functions && Object.keys(options.functions).length > 0) ||
2510-
(options.importer &&
2511-
(!Array.isArray(options.importer) ||
2512-
options.importer.length > 0)) ||
2513-
options.logger ||
2514-
options.pkgImporter
2515-
)
2516-
},
2517-
max: maxWorkers,
2518-
},
2519-
)
2520-
return worker
2521-
}
2522-
25232378
const makeModernScssWorker = (
25242379
environment: PartialEnvironment,
25252380
resolvers: CSSAtImportResolvers,
@@ -2741,7 +2596,7 @@ const makeModernCompilerScssWorker = (
27412596
type ScssWorkerResult = {
27422597
css: string
27432598
map?: string | undefined
2744-
stats: Pick<Sass.LegacyResult['stats'], 'includedFiles'>
2599+
stats: { includedFiles: string[] }
27452600
}
27462601

27472602
const scssProcessor = (
@@ -2750,9 +2605,7 @@ const scssProcessor = (
27502605
const workerMap = new Map<
27512606
unknown,
27522607
ReturnType<
2753-
| typeof makeScssWorker
2754-
| typeof makeModernScssWorker
2755-
| typeof makeModernCompilerScssWorker
2608+
typeof makeModernScssWorker | typeof makeModernCompilerScssWorker
27562609
>
27572610
>()
27582611

@@ -2778,20 +2631,12 @@ const scssProcessor = (
27782631
options.alias,
27792632
maxWorkers,
27802633
)
2781-
: api === 'modern'
2782-
? makeModernScssWorker(
2783-
environment,
2784-
resolvers,
2785-
options.alias,
2786-
maxWorkers,
2787-
)
2788-
: makeScssWorker(
2789-
environment,
2790-
resolvers,
2791-
options.alias,
2792-
maxWorkers,
2793-
sassPackage.name,
2794-
),
2634+
: makeModernScssWorker(
2635+
environment,
2636+
resolvers,
2637+
options.alias,
2638+
maxWorkers,
2639+
),
27952640
)
27962641
}
27972642
const worker = workerMap.get(options.alias)!
@@ -3317,11 +3162,7 @@ const createPreprocessorWorkerController = (maxWorkers: number | undefined) => {
33173162
const sassProcess: StylePreprocessor<SassStylePreprocessorInternalOptions>['process'] =
33183163
(environment, source, root, options, resolvers) => {
33193164
const opts: SassStylePreprocessorInternalOptions = { ...options }
3320-
if (opts.api === 'legacy') {
3321-
opts.indentedSyntax = true
3322-
} else {
3323-
opts.syntax = 'indented'
3324-
}
3165+
opts.syntax = 'indented'
33253166
return scss.process(environment, source, root, opts, resolvers)
33263167
}
33273168

packages/vite/types/internal/cssPreprocessorOptions.d.ts

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,6 @@ import type Stylus from 'stylus'
1414
// https://github.com/type-challenges/type-challenges/issues/29285
1515
type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false
1616

17-
type DartSassLegacyStringOptionsAsync = DartSass.LegacyStringOptions<'async'>
18-
type SassEmbeddedLegacyStringOptionsAsync =
19-
SassEmbedded.LegacyStringOptions<'async'>
20-
type SassLegacyStringOptionsAsync =
21-
IsAny<DartSassLegacyStringOptionsAsync> extends false
22-
? DartSassLegacyStringOptionsAsync
23-
: SassEmbeddedLegacyStringOptionsAsync
24-
25-
export type SassLegacyPreprocessBaseOptions = Omit<
26-
SassLegacyStringOptionsAsync,
27-
| 'data'
28-
| 'file'
29-
| 'outFile'
30-
| 'sourceMap'
31-
| 'omitSourceMapUrl'
32-
| 'sourceMapEmbed'
33-
| 'sourceMapRoot'
34-
>
35-
3617
type DartSassStringOptionsAsync = DartSass.StringOptions<'async'>
3718
type SassEmbeddedStringOptionsAsync = SassEmbedded.StringOptions<'async'>
3819
type SassStringOptionsAsync =

playground/css-sourcemap/__tests__/sass-legacy/sass-legacy.spec.ts

Lines changed: 0 additions & 2 deletions
This file was deleted.

playground/css-sourcemap/vite.config-sass-legacy.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

playground/css/__tests__/sass-legacy/sass-legacy.spec.ts

Lines changed: 0 additions & 6 deletions
This file was deleted.

playground/css/vite.config-sass-legacy.js

Lines changed: 0 additions & 34 deletions
This file was deleted.

playground/vitestGlobalSetup.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ export async function setup({ provide }: TestProject): Promise<void> {
4343
})
4444
// also setup dedicated copy for "variant" tests
4545
for (const [original, variants] of [
46-
['css', ['sass-legacy', 'sass-modern', 'lightningcss']],
47-
['css-sourcemap', ['sass-legacy', 'sass-modern']],
46+
['css', ['sass-modern', 'lightningcss']],
47+
['css-sourcemap', ['sass-modern']],
4848
['transform-plugin', ['base']],
4949
] as const) {
5050
for (const variant of variants) {

0 commit comments

Comments
 (0)