Skip to content

Commit

Permalink
fix(css): css file emit synchronously (#12558)
Browse files Browse the repository at this point in the history
Co-authored-by: bluwy <bjornlu.dev@gmail.com>
  • Loading branch information
sun0day and bluwy authored Apr 5, 2023
1 parent 4ffaeee commit 8e30025
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 58 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
"prompts": "^2.4.2",
"resolve": "^1.22.1",
"rimraf": "^4.4.0",
"rollup": "^3.20.0",
"rollup": "^3.20.2",
"semver": "^7.3.8",
"simple-git-hooks": "^2.8.1",
"tslib": "^2.5.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"esbuild": "^0.17.5",
"postcss": "^8.4.21",
"resolve": "^1.22.1",
"rollup": "^3.20.0"
"rollup": "^3.20.2"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
Expand Down
25 changes: 24 additions & 1 deletion packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ export function cssPlugin(config: ResolvedConfig): Plugin {
export function cssPostPlugin(config: ResolvedConfig): Plugin {
// styles initialization in buildStart causes a styling loss in watch
const styles: Map<string, string> = new Map<string, string>()
// list of css emit tasks to guarantee the files are emitted in a deterministic order
let emitTasks: Promise<void>[] = []
let pureCssChunks: Set<RenderedChunk>

// when there are multiple rollup outputs and extracting CSS, only emit once,
Expand Down Expand Up @@ -353,6 +355,7 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
pureCssChunks = new Set<RenderedChunk>()
outputToExtractedCSSMap = new Map<NormalizedOutputOptions, string>()
hasEmitted = false
emitTasks = []
},

async transform(css, id, options) {
Expand Down Expand Up @@ -563,7 +566,22 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
const cssFileName = ensureFileExt(cssAssetName, '.css')

chunkCSS = resolveAssetUrlsInCss(chunkCSS, cssAssetName)
chunkCSS = await finalizeCss(chunkCSS, true, config)

const previousTask = emitTasks[emitTasks.length - 1]
// finalizeCss is async which makes `emitFile` non-deterministic, so
// we use a `.then` to wait for previous tasks before finishing this
const thisTask = finalizeCss(chunkCSS, true, config).then((css) => {
chunkCSS = css
// make sure the previous task is also finished, this works recursively
return previousTask
})

// push this task so the next task can wait for this one
emitTasks.push(thisTask)
const emitTasksLength = emitTasks.length

// wait for this and previous tasks to finish
await thisTask

// emit corresponding css file
const referenceId = this.emitFile({
Expand All @@ -577,6 +595,11 @@ export function cssPostPlugin(config: ResolvedConfig): Plugin {
.get(config)!
.set(referenceId, { originalName, isEntry })
chunk.viteMetadata!.importedCss.add(this.getFileName(referenceId))

if (emitTasksLength === emitTasks.length) {
// this is the last task, clear `emitTasks` to free up memory
emitTasks = []
}
} else if (!config.build.ssr) {
// legacy build and inline css

Expand Down
110 changes: 55 additions & 55 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 8e30025

Please sign in to comment.