From 3a9764403722a32b8d51222025e6516ef557e178 Mon Sep 17 00:00:00 2001 From: OneNail <31649110+OneNail@users.noreply.github.com> Date: Tue, 20 Jul 2021 20:24:50 +0800 Subject: [PATCH] fix(css): cachedPostcssConfig reused for multiple builds (#3906) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(css): cachedPostcssConfig reused for multiple builds * fix: add tests to demonstrate that PostCSS configs are not reused across projects * fix: run everything in a single Jest test to ensure module cache isn't cleared Co-authored-by: François Wouts --- .../css/postcss-caching/blue-app/imported.css | 3 ++ .../css/postcss-caching/blue-app/index.html | 12 +++++ .../css/postcss-caching/blue-app/main.js | 6 +++ .../css/postcss-caching/blue-app/package.json | 11 +++++ .../blue-app/postcss.config.js | 15 ++++++ .../css/postcss-caching/css.spec.ts | 29 ++++++++++++ .../postcss-caching/green-app/imported.css | 3 ++ .../css/postcss-caching/green-app/index.html | 12 +++++ .../css/postcss-caching/green-app/main.js | 6 +++ .../postcss-caching/green-app/package.json | 11 +++++ .../green-app/postcss.config.js | 15 ++++++ packages/vite/src/node/plugins/css.ts | 46 +++++++++++-------- 12 files changed, 150 insertions(+), 19 deletions(-) create mode 100644 packages/playground/css/postcss-caching/blue-app/imported.css create mode 100644 packages/playground/css/postcss-caching/blue-app/index.html create mode 100644 packages/playground/css/postcss-caching/blue-app/main.js create mode 100644 packages/playground/css/postcss-caching/blue-app/package.json create mode 100644 packages/playground/css/postcss-caching/blue-app/postcss.config.js create mode 100644 packages/playground/css/postcss-caching/css.spec.ts create mode 100644 packages/playground/css/postcss-caching/green-app/imported.css create mode 100644 packages/playground/css/postcss-caching/green-app/index.html create mode 100644 packages/playground/css/postcss-caching/green-app/main.js create mode 100644 packages/playground/css/postcss-caching/green-app/package.json create mode 100644 packages/playground/css/postcss-caching/green-app/postcss.config.js diff --git a/packages/playground/css/postcss-caching/blue-app/imported.css b/packages/playground/css/postcss-caching/blue-app/imported.css new file mode 100644 index 00000000000000..2db9597eed1011 --- /dev/null +++ b/packages/playground/css/postcss-caching/blue-app/imported.css @@ -0,0 +1,3 @@ +.postcss-a { + color: pink; +} diff --git a/packages/playground/css/postcss-caching/blue-app/index.html b/packages/playground/css/postcss-caching/blue-app/index.html new file mode 100644 index 00000000000000..48bc3c24d3a262 --- /dev/null +++ b/packages/playground/css/postcss-caching/blue-app/index.html @@ -0,0 +1,12 @@ +
+

CSS

+ +

Imported css string:

+

+
+  

This should be blue

+ +

This should be black

+
+ + diff --git a/packages/playground/css/postcss-caching/blue-app/main.js b/packages/playground/css/postcss-caching/blue-app/main.js new file mode 100644 index 00000000000000..53286e882053fa --- /dev/null +++ b/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 +} diff --git a/packages/playground/css/postcss-caching/blue-app/package.json b/packages/playground/css/postcss-caching/blue-app/package.json new file mode 100644 index 00000000000000..542b4f5711180e --- /dev/null +++ b/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" + } +} diff --git a/packages/playground/css/postcss-caching/blue-app/postcss.config.js b/packages/playground/css/postcss-caching/blue-app/postcss.config.js new file mode 100644 index 00000000000000..2506cd535feef7 --- /dev/null +++ b/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 diff --git a/packages/playground/css/postcss-caching/css.spec.ts b/packages/playground/css/postcss-caching/css.spec.ts new file mode 100644 index 00000000000000..835538666db7bb --- /dev/null +++ b/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() +}) diff --git a/packages/playground/css/postcss-caching/green-app/imported.css b/packages/playground/css/postcss-caching/green-app/imported.css new file mode 100644 index 00000000000000..8fd68a56a7284d --- /dev/null +++ b/packages/playground/css/postcss-caching/green-app/imported.css @@ -0,0 +1,3 @@ +.postcss-b { + color: pink; +} diff --git a/packages/playground/css/postcss-caching/green-app/index.html b/packages/playground/css/postcss-caching/green-app/index.html new file mode 100644 index 00000000000000..4c0428b578e03e --- /dev/null +++ b/packages/playground/css/postcss-caching/green-app/index.html @@ -0,0 +1,12 @@ +
+

CSS

+ +

Imported css string:

+

+
+  

This should be black

+ +

This should be green

+
+ + diff --git a/packages/playground/css/postcss-caching/green-app/main.js b/packages/playground/css/postcss-caching/green-app/main.js new file mode 100644 index 00000000000000..53286e882053fa --- /dev/null +++ b/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 +} diff --git a/packages/playground/css/postcss-caching/green-app/package.json b/packages/playground/css/postcss-caching/green-app/package.json new file mode 100644 index 00000000000000..1ac4969a18eccd --- /dev/null +++ b/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" + } +} diff --git a/packages/playground/css/postcss-caching/green-app/postcss.config.js b/packages/playground/css/postcss-caching/green-app/postcss.config.js new file mode 100644 index 00000000000000..1367dfc1d27c7b --- /dev/null +++ b/packages/playground/css/postcss-caching/green-app/postcss.config.js @@ -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 diff --git a/packages/vite/src/node/plugins/css.ts b/packages/vite/src/node/plugins/css.ts index f2d358d29133d0..8b3108ab8b6b80 100644 --- a/packages/vite/src/node/plugins/css.ts +++ b/packages/vite/src/node/plugins/css.ts @@ -115,6 +115,11 @@ export const chunkToEmittedCssFileMap = new WeakMap< Set >() +const postcssConfigCache = new WeakMap< + ResolvedConfig, + PostCSSConfigResult | null +>() + /** * Plugin applied before user plugins */ @@ -729,37 +734,40 @@ interface PostCSSConfigResult { plugins: Postcss.Plugin[] } -let cachedPostcssConfig: PostCSSConfigResult | null | undefined - async function resolvePostcssConfig( config: ResolvedConfig ): Promise { - 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 = (