From 955f96813b3b4442acdb8322450506c017df0578 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Thu, 20 Oct 2022 06:30:59 -0400 Subject: [PATCH 1/5] Record and watch PostCSS dependencies in the CLI --- .../tailwindcss-cli/tests/cli.test.js | 25 +++++++++++++++++++ src/cli/build/plugin.js | 20 +++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/integrations/tailwindcss-cli/tests/cli.test.js b/integrations/tailwindcss-cli/tests/cli.test.js index 41ff2de4ebab..b43f2975aa1f 100644 --- a/integrations/tailwindcss-cli/tests/cli.test.js +++ b/integrations/tailwindcss-cli/tests/cli.test.js @@ -411,6 +411,31 @@ describe('Build command', () => { ` ) + await writeInputFile( + 'imported.css', + css` + @layer utilities { + .something-cool { + color: blue; + } + } + ` + ) + + await runningProcess.onStderr(function ready(message) { + return message.includes('Done in') + }) + + expect(await readOutputFile('main.css')).toIncludeCss( + css` + @media (min-width: 768px) { + .md\:something-cool { + color: blue; + } + } + ` + ) + return runningProcess.stop() }) diff --git a/src/cli/build/plugin.js b/src/cli/build/plugin.js index 51177db79113..a06bca3be1ae 100644 --- a/src/cli/build/plugin.js +++ b/src/cli/build/plugin.js @@ -328,6 +328,26 @@ export async function createProcessor(args, cliConfigPath) { return readInput() .then((css) => processor.process(css, { ...postcssOptions, from: input, to: output })) + .then((result) => { + if (!state.watcher) { + return result + } + + env.DEBUG && console.time('Recording PostCSS dependencies') + for (let message of result.messages) { + if (message.type === 'dependency') { + state.contextDependencies.add(message.file) + } + } + env.DEBUG && console.timeEnd('Recording PostCSS dependencies') + + // TODO: This needs to be in a different spot + env.DEBUG && console.time('Watch new files') + state.watcher.refreshWatchedFiles() + env.DEBUG && console.timeEnd('Watch new files') + + return result + }) .then((result) => { if (!output) { process.stdout.write(result.css) From 1a15f224ba420567a0bf5a6683a1d26e337721a9 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 20 Oct 2022 17:10:16 +0200 Subject: [PATCH 2/5] ensure `changedContent` gets cleared Otherwise this list gets bigger and bigger, not only that there is a subtle bug. The moment you save a `.css` file we want to create a new context and start from scratch. However, since the list was never cleared, it meant that every subsequent save to *any* file (not only config / css files) creates a new context... By clearing the least we should work around this problem. --- src/cli/build/watching.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/build/watching.js b/src/cli/build/watching.js index 8ebceccf5cc7..9b5462a244fd 100644 --- a/src/cli/build/watching.js +++ b/src/cli/build/watching.js @@ -62,7 +62,7 @@ export function createWatcher(args, { state, rebuild }) { extension: path.extname(file).slice(1), }) - chain = chain.then(() => rebuild(changedContent)) + chain = chain.then(() => rebuild(changedContent.splice(0))) return chain } From d6625eb65990a0f78e84145fa07938b6ec44bb3f Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 20 Oct 2022 17:33:40 +0200 Subject: [PATCH 3/5] add test that verifies an odd bug The story goes like this: 1. add `underline` to html file -> css contains `underline` rule 2. add `font-bold` to html file -> css contains `underline` and `font-bold` 3. remove `underline` from html file -> css still contains `underline` and `font-bold` for performance reasons 4. Save a css file (! RED FLAG) -> css contains `font-bold` because we started from scratch 5. add `underline` to html file -> css contains `underline` and `font-bold` 6. remove `underline` from html file -> css only contains `font-bold`... (UH OH) This is because the moment we did step 4, every single save in any file created a new context. Every. Single. Time. --- .../tailwindcss-cli/tests/integration.test.js | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/integrations/tailwindcss-cli/tests/integration.test.js b/integrations/tailwindcss-cli/tests/integration.test.js index fbfdc6f0db96..4948ef4da9dc 100644 --- a/integrations/tailwindcss-cli/tests/integration.test.js +++ b/integrations/tailwindcss-cli/tests/integration.test.js @@ -605,4 +605,105 @@ describe('watcher', () => { return runningProcess.stop() }) + + test('classes are generated (and kept) when the index.html file changes (and removed when css/config files are changed)', async () => { + let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w') + + // Start with a simple single class + await writeInputFile('index.html', html`
`) + await runningProcess.onStderr(ready) + expect(await readOutputFile('main.css')).toIncludeCss( + css` + .font-bold { + font-weight: 700; + } + ` + ) + + // Add another class + await writeInputFile('index.html', html`
`) + await runningProcess.onStderr(ready) + expect(await readOutputFile('main.css')).toIncludeCss( + css` + .font-bold { + font-weight: 700; + } + + .underline { + text-decoration-line: underline; + } + ` + ) + + // Remove a class, because of performance reasons both classes will still be in the css file + await writeInputFile('index.html', html`
`) + await runningProcess.onStderr(ready) + expect(await readOutputFile('main.css')).toIncludeCss( + css` + .font-bold { + font-weight: 700; + } + + .underline { + text-decoration-line: underline; + } + ` + ) + + // Save the index.css file, this should trigger a fresh context + await writeInputFile( + 'index.css', + css` + @tailwind base; + @tailwind components; + @tailwind utilities; + ` + ) + await runningProcess.onStderr(ready) + + // Only 1 class should stay, because we started from scratch + expect(await readOutputFile('main.css')).toIncludeCss( + css` + .font-bold { + font-weight: 700; + } + ` + ) + + // Add another class + await writeInputFile('index.html', html`
`) + await runningProcess.onStderr(ready) + expect(await readOutputFile('main.css')).toIncludeCss( + css` + .font-bold { + font-weight: 700; + } + + .underline { + text-decoration-line: underline; + } + ` + ) + + // Remove a class, because of performance reasons both classes will still be in the css file + await writeInputFile('index.html', html`
`) + await runningProcess.onStderr(ready) + + // If everything goes right, then both classes should still be here (because of the performance + // improvement). If we didn't solve the bug where from now on every save is a fresh context + // then this only has 1 class. So let's hope there are 2! + expect(await readOutputFile('main.css')).toIncludeCss( + css` + .font-bold { + font-weight: 700; + } + + .underline { + text-decoration-line: underline; + } + ` + ) + + return runningProcess.stop() + }) }) From c426d106201aa79287303bf0686475b30cc4a8b6 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 20 Oct 2022 17:55:06 +0200 Subject: [PATCH 4/5] use a property that doesn't require `autoprefixer` --- .../tailwindcss-cli/tests/integration.test.js | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/integrations/tailwindcss-cli/tests/integration.test.js b/integrations/tailwindcss-cli/tests/integration.test.js index 4948ef4da9dc..4a76cdfeff26 100644 --- a/integrations/tailwindcss-cli/tests/integration.test.js +++ b/integrations/tailwindcss-cli/tests/integration.test.js @@ -621,16 +621,16 @@ describe('watcher', () => { ) // Add another class - await writeInputFile('index.html', html`
`) + await writeInputFile('index.html', html`
`) await runningProcess.onStderr(ready) expect(await readOutputFile('main.css')).toIncludeCss( css` - .font-bold { - font-weight: 700; + .flex { + display: flex; } - .underline { - text-decoration-line: underline; + .font-bold { + font-weight: 700; } ` ) @@ -640,12 +640,12 @@ describe('watcher', () => { await runningProcess.onStderr(ready) expect(await readOutputFile('main.css')).toIncludeCss( css` - .font-bold { - font-weight: 700; + .flex { + display: flex; } - .underline { - text-decoration-line: underline; + .font-bold { + font-weight: 700; } ` ) @@ -671,16 +671,16 @@ describe('watcher', () => { ) // Add another class - await writeInputFile('index.html', html`
`) + await writeInputFile('index.html', html`
`) await runningProcess.onStderr(ready) expect(await readOutputFile('main.css')).toIncludeCss( css` - .font-bold { - font-weight: 700; + .flex { + display: flex; } - .underline { - text-decoration-line: underline; + .font-bold { + font-weight: 700; } ` ) @@ -694,12 +694,12 @@ describe('watcher', () => { // then this only has 1 class. So let's hope there are 2! expect(await readOutputFile('main.css')).toIncludeCss( css` - .font-bold { - font-weight: 700; + .flex { + display: flex; } - .underline { - text-decoration-line: underline; + .font-bold { + font-weight: 700; } ` ) From 33f0513eb48c46ad12004871660ee484f3ecb67c Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 20 Oct 2022 17:57:19 +0200 Subject: [PATCH 5/5] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f5bd398bda8..9a8efd6b0158 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fix missing `supports` in types ([#9616](https://github.com/tailwindlabs/tailwindcss/pull/9616)) +- Fix missing PostCSS dependencies in the CLI ([#9617](https://github.com/tailwindlabs/tailwindcss/pull/9617)) ## [3.2.0] - 2022-10-19