Skip to content

Commit c02fac4

Browse files
authoredJul 7, 2023
fix(css): use single postcss instance (#13738)
1 parent 487bdcd commit c02fac4

File tree

1 file changed

+85
-61
lines changed
  • packages/vite/src/node/plugins

1 file changed

+85
-61
lines changed
 

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

+85-61
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,72 @@ function getCssResolversKeys(
858858
return Object.keys(resolvers) as unknown as Array<keyof CSSAtImportResolvers>
859859
}
860860

861+
async function compileCSSPreprocessors(
862+
id: string,
863+
lang: PreprocessLang,
864+
code: string,
865+
config: ResolvedConfig,
866+
): Promise<{ code: string; map?: ExistingRawSourceMap; deps?: Set<string> }> {
867+
const { preprocessorOptions, devSourcemap } = config.css ?? {}
868+
const atImportResolvers = getAtImportResolvers(config)
869+
870+
const preProcessor = preProcessors[lang]
871+
let opts = (preprocessorOptions && preprocessorOptions[lang]) || {}
872+
// support @import from node dependencies by default
873+
switch (lang) {
874+
case PreprocessLang.scss:
875+
case PreprocessLang.sass:
876+
opts = {
877+
includePaths: ['node_modules'],
878+
alias: config.resolve.alias,
879+
...opts,
880+
}
881+
break
882+
case PreprocessLang.less:
883+
case PreprocessLang.styl:
884+
case PreprocessLang.stylus:
885+
opts = {
886+
paths: ['node_modules'],
887+
alias: config.resolve.alias,
888+
...opts,
889+
}
890+
}
891+
// important: set this for relative import resolving
892+
opts.filename = cleanUrl(id)
893+
opts.enableSourcemap = devSourcemap ?? false
894+
895+
const preprocessResult = await preProcessor(
896+
code,
897+
config.root,
898+
opts,
899+
atImportResolvers,
900+
)
901+
if (preprocessResult.error) {
902+
throw preprocessResult.error
903+
}
904+
905+
let deps: Set<string> | undefined
906+
if (preprocessResult.deps) {
907+
const normalizedFilename = normalizePath(opts.filename)
908+
// sometimes sass registers the file itself as a dep
909+
deps = new Set(
910+
[...preprocessResult.deps].filter(
911+
(dep) => normalizePath(dep) !== normalizedFilename,
912+
),
913+
)
914+
}
915+
916+
return {
917+
code: preprocessResult.code,
918+
map: combineSourcemapsIfExists(
919+
opts.filename,
920+
preprocessResult.map,
921+
preprocessResult.additionalMap,
922+
),
923+
deps,
924+
}
925+
}
926+
861927
const configToAtImportResolvers = new WeakMap<
862928
ResolvedConfig,
863929
CSSAtImportResolvers
@@ -887,11 +953,7 @@ async function compileCSS(
887953
return compileLightningCSS(id, code, config, urlReplacer)
888954
}
889955

890-
const {
891-
modules: modulesOptions,
892-
preprocessorOptions,
893-
devSourcemap,
894-
} = config.css || {}
956+
const { modules: modulesOptions, devSourcemap } = config.css || {}
895957
const isModule = modulesOptions !== false && cssModuleRE.test(id)
896958
// although at serve time it can work without processing, we do need to
897959
// crawl them in order to register watch dependencies.
@@ -911,68 +973,25 @@ async function compileCSS(
911973
return { code, map: null }
912974
}
913975

914-
let preprocessorMap: ExistingRawSourceMap | undefined
915976
let modules: Record<string, string> | undefined
916977
const deps = new Set<string>()
917978

918-
const atImportResolvers = getAtImportResolvers(config)
919-
920979
// 2. pre-processors: sass etc.
980+
let preprocessorMap: ExistingRawSourceMap | undefined
921981
if (isPreProcessor(lang)) {
922-
const preProcessor = preProcessors[lang]
923-
let opts = (preprocessorOptions && preprocessorOptions[lang]) || {}
924-
// support @import from node dependencies by default
925-
switch (lang) {
926-
case PreprocessLang.scss:
927-
case PreprocessLang.sass:
928-
opts = {
929-
includePaths: ['node_modules'],
930-
alias: config.resolve.alias,
931-
...opts,
932-
}
933-
break
934-
case PreprocessLang.less:
935-
case PreprocessLang.styl:
936-
case PreprocessLang.stylus:
937-
opts = {
938-
paths: ['node_modules'],
939-
alias: config.resolve.alias,
940-
...opts,
941-
}
942-
}
943-
// important: set this for relative import resolving
944-
opts.filename = cleanUrl(id)
945-
opts.enableSourcemap = devSourcemap ?? false
946-
947-
const preprocessResult = await preProcessor(
982+
const preprocessorResult = await compileCSSPreprocessors(
983+
id,
984+
lang,
948985
code,
949-
config.root,
950-
opts,
951-
atImportResolvers,
986+
config,
952987
)
953-
954-
if (preprocessResult.error) {
955-
throw preprocessResult.error
956-
}
957-
958-
code = preprocessResult.code
959-
preprocessorMap = combineSourcemapsIfExists(
960-
opts.filename,
961-
preprocessResult.map,
962-
preprocessResult.additionalMap,
963-
)
964-
965-
if (preprocessResult.deps) {
966-
preprocessResult.deps.forEach((dep) => {
967-
// sometimes sass registers the file itself as a dep
968-
if (normalizePath(dep) !== normalizePath(opts.filename)) {
969-
deps.add(dep)
970-
}
971-
})
972-
}
988+
code = preprocessorResult.code
989+
preprocessorMap = preprocessorResult.map
990+
preprocessorResult.deps?.forEach((dep) => deps.add(dep))
973991
}
974992

975993
// 3. postcss
994+
const atImportResolvers = getAtImportResolvers(config)
976995
const postcssOptions = (postcssConfig && postcssConfig.options) || {}
977996

978997
const postcssPlugins =
@@ -1010,10 +1029,15 @@ async function compileCSS(
10101029
return id
10111030
},
10121031
async load(id) {
1013-
const code = fs.readFileSync(id, 'utf-8')
1014-
const result = await compileCSS(id, code, config)
1015-
result.deps?.forEach((dep) => deps.add(dep))
1016-
return result.code
1032+
const code = await fs.promises.readFile(id, 'utf-8')
1033+
const lang = id.match(CSS_LANGS_RE)?.[1] as CssLang | undefined
1034+
if (isPreProcessor(lang)) {
1035+
const result = await compileCSSPreprocessors(id, lang, code, config)
1036+
result.deps?.forEach((dep) => deps.add(dep))
1037+
// TODO: support source map
1038+
return result.code
1039+
}
1040+
return code
10171041
},
10181042
nameLayer(index) {
10191043
return `vite--anon-layer-${getHash(id)}-${index}`

0 commit comments

Comments
 (0)
Please sign in to comment.