Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(css): cachedPostcssConfig reused for multiple builds #3906

Merged
merged 4 commits into from Jul 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/playground/css/postcss-caching/blue-app/imported.css
@@ -0,0 +1,3 @@
.postcss-a {
color: pink;
}
12 changes: 12 additions & 0 deletions packages/playground/css/postcss-caching/blue-app/index.html
@@ -0,0 +1,12 @@
<div class="wrapper">
<h1>CSS</h1>

<p>Imported css string:</p>
<pre class="imported-css"></pre>

<p class="postcss-a">This should be blue</p>

<p class="postcss-b">This should be black</p>
</div>

<script type="module" src="./main.js"></script>
6 changes: 6 additions & 0 deletions packages/playground/css/postcss-caching/blue-app/main.js
@@ -0,0 +1,6 @@
import css from './imported.css'
text('.imported-css', css)

function text(el, text) {
document.querySelector(el).textContent = text
}
11 changes: 11 additions & 0 deletions packages/playground/css/postcss-caching/blue-app/package.json
@@ -0,0 +1,11 @@
{
"name": "blue-app",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"debug": "node --inspect-brk ../../vite/bin/vite",
"serve": "vite preview"
}
}
15 changes: 15 additions & 0 deletions packages/playground/css/postcss-caching/blue-app/postcss.config.js
@@ -0,0 +1,15 @@
module.exports = {
plugins: [replacePinkWithBlue]
}

function replacePinkWithBlue() {
return {
postcssPlugin: 'replace-pink-with-blue',
Declaration(decl) {
if (decl.value === 'pink') {
decl.value = 'blue'
}
}
}
}
replacePinkWithBlue.postcss = true
29 changes: 29 additions & 0 deletions packages/playground/css/postcss-caching/css.spec.ts
@@ -0,0 +1,29 @@
import { getColor } from '../../testUtils'
import { createServer } from 'vite'
import path from 'path'

test('postcss config', async () => {
const port = 5005
const blueAppDir = path.join(__dirname, 'blue-app')
const greenAppDir = path.join(__dirname, 'green-app')

process.chdir(blueAppDir)
const blueApp = await createServer()
await blueApp.listen(port)
await page.goto(`http://localhost:${port}`)
const blueA = await page.$('.postcss-a')
expect(await getColor(blueA)).toBe('blue')
const blueB = await page.$('.postcss-b')
expect(await getColor(blueB)).toBe('black')
await blueApp.close()

process.chdir(greenAppDir)
const greenApp = await createServer()
await greenApp.listen(port)
await page.goto(`http://localhost:${port}`)
const greenA = await page.$('.postcss-a')
expect(await getColor(greenA)).toBe('black')
const greenB = await page.$('.postcss-b')
expect(await getColor(greenB)).toBe('green')
await greenApp.close()
})
@@ -0,0 +1,3 @@
.postcss-b {
color: pink;
}
12 changes: 12 additions & 0 deletions packages/playground/css/postcss-caching/green-app/index.html
@@ -0,0 +1,12 @@
<div class="wrapper">
<h1>CSS</h1>

<p>Imported css string:</p>
<pre class="imported-css"></pre>

<p class="postcss-a">This should be black</p>

<p class="postcss-b">This should be green</p>
</div>

<script type="module" src="./main.js"></script>
6 changes: 6 additions & 0 deletions packages/playground/css/postcss-caching/green-app/main.js
@@ -0,0 +1,6 @@
import css from './imported.css'
text('.imported-css', css)

function text(el, text) {
document.querySelector(el).textContent = text
}
11 changes: 11 additions & 0 deletions packages/playground/css/postcss-caching/green-app/package.json
@@ -0,0 +1,11 @@
{
"name": "green-app",
"private": true,
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"debug": "node --inspect-brk ../../vite/bin/vite",
"serve": "vite preview"
}
}
@@ -0,0 +1,15 @@
module.exports = {
plugins: [replacePinkWithGreen]
}

function replacePinkWithGreen() {
return {
postcssPlugin: 'replace-pink-with-green',
Declaration(decl) {
if (decl.value === 'pink') {
decl.value = 'green'
}
}
}
}
replacePinkWithGreen.postcss = true
46 changes: 27 additions & 19 deletions packages/vite/src/node/plugins/css.ts
Expand Up @@ -114,6 +114,11 @@ export const chunkToEmittedCssFileMap = new WeakMap<
Set<string>
>()

const postcssConfigCache = new WeakMap<
ResolvedConfig,
PostCSSConfigResult | null
>()

/**
* Plugin applied before user plugins
*/
Expand Down Expand Up @@ -720,37 +725,40 @@ interface PostCSSConfigResult {
plugins: Postcss.Plugin[]
}

let cachedPostcssConfig: PostCSSConfigResult | null | undefined

async function resolvePostcssConfig(
config: ResolvedConfig
): Promise<PostCSSConfigResult | null> {
if (cachedPostcssConfig !== undefined) {
return cachedPostcssConfig
let result = postcssConfigCache.get(config)
if (result !== undefined) {
return result
}

// inline postcss config via vite config
const inlineOptions = config.css?.postcss
if (isObject(inlineOptions)) {
const result = {
options: { ...inlineOptions },
const options = { ...inlineOptions }

delete options.plugins
result = {
options,
plugins: inlineOptions.plugins || []
}
delete result.options.plugins
return (cachedPostcssConfig = result)
}

try {
const searchPath =
typeof inlineOptions === 'string' ? inlineOptions : config.root
// @ts-ignore
return (cachedPostcssConfig = await postcssrc({}, searchPath))
} catch (e) {
if (!/No PostCSS Config found/.test(e.message)) {
throw e
} else {
try {
const searchPath =
typeof inlineOptions === 'string' ? inlineOptions : config.root
// @ts-ignore
result = await postcssrc({}, searchPath)
} catch (e) {
if (!/No PostCSS Config found/.test(e.message)) {
throw e
}
result = null
}
return (cachedPostcssConfig = null)
}

postcssConfigCache.set(config, result)
return result
}

type CssUrlReplacer = (
Expand Down