Skip to content

Commit 40f6b4f

Browse files
Fix missing PostCSS dependencies in the CLI (#9617)
* Record and watch PostCSS dependencies in the CLI * 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. * 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. * use a property that doesn't require `autoprefixer` * update changelog Co-authored-by: Jordan Pittman <[email protected]>
1 parent 4dfb1e3 commit 40f6b4f

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Fixed
1111

1212
- Fix missing `supports` in types ([#9616](https://github.com/tailwindlabs/tailwindcss/pull/9616))
13+
- Fix missing PostCSS dependencies in the CLI ([#9617](https://github.com/tailwindlabs/tailwindcss/pull/9617))
1314

1415
## [3.2.0] - 2022-10-19
1516

integrations/tailwindcss-cli/tests/cli.test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,31 @@ describe('Build command', () => {
411411
`
412412
)
413413

414+
await writeInputFile(
415+
'imported.css',
416+
css`
417+
@layer utilities {
418+
.something-cool {
419+
color: blue;
420+
}
421+
}
422+
`
423+
)
424+
425+
await runningProcess.onStderr(function ready(message) {
426+
return message.includes('Done in')
427+
})
428+
429+
expect(await readOutputFile('main.css')).toIncludeCss(
430+
css`
431+
@media (min-width: 768px) {
432+
.md\:something-cool {
433+
color: blue;
434+
}
435+
}
436+
`
437+
)
438+
414439
return runningProcess.stop()
415440
})
416441

integrations/tailwindcss-cli/tests/integration.test.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,4 +605,105 @@ describe('watcher', () => {
605605

606606
return runningProcess.stop()
607607
})
608+
609+
test('classes are generated (and kept) when the index.html file changes (and removed when css/config files are changed)', async () => {
610+
let runningProcess = $('node ../../lib/cli.js -i ./src/index.css -o ./dist/main.css -w')
611+
612+
// Start with a simple single class
613+
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
614+
await runningProcess.onStderr(ready)
615+
expect(await readOutputFile('main.css')).toIncludeCss(
616+
css`
617+
.font-bold {
618+
font-weight: 700;
619+
}
620+
`
621+
)
622+
623+
// Add another class
624+
await writeInputFile('index.html', html`<div class="flex font-bold"></div>`)
625+
await runningProcess.onStderr(ready)
626+
expect(await readOutputFile('main.css')).toIncludeCss(
627+
css`
628+
.flex {
629+
display: flex;
630+
}
631+
632+
.font-bold {
633+
font-weight: 700;
634+
}
635+
`
636+
)
637+
638+
// Remove a class, because of performance reasons both classes will still be in the css file
639+
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
640+
await runningProcess.onStderr(ready)
641+
expect(await readOutputFile('main.css')).toIncludeCss(
642+
css`
643+
.flex {
644+
display: flex;
645+
}
646+
647+
.font-bold {
648+
font-weight: 700;
649+
}
650+
`
651+
)
652+
653+
// Save the index.css file, this should trigger a fresh context
654+
await writeInputFile(
655+
'index.css',
656+
css`
657+
@tailwind base;
658+
@tailwind components;
659+
@tailwind utilities;
660+
`
661+
)
662+
await runningProcess.onStderr(ready)
663+
664+
// Only 1 class should stay, because we started from scratch
665+
expect(await readOutputFile('main.css')).toIncludeCss(
666+
css`
667+
.font-bold {
668+
font-weight: 700;
669+
}
670+
`
671+
)
672+
673+
// Add another class
674+
await writeInputFile('index.html', html`<div class="flex font-bold"></div>`)
675+
await runningProcess.onStderr(ready)
676+
expect(await readOutputFile('main.css')).toIncludeCss(
677+
css`
678+
.flex {
679+
display: flex;
680+
}
681+
682+
.font-bold {
683+
font-weight: 700;
684+
}
685+
`
686+
)
687+
688+
// Remove a class, because of performance reasons both classes will still be in the css file
689+
await writeInputFile('index.html', html`<div class="font-bold"></div>`)
690+
await runningProcess.onStderr(ready)
691+
692+
// If everything goes right, then both classes should still be here (because of the performance
693+
// improvement). If we didn't solve the bug where from now on every save is a fresh context
694+
// then this only has 1 class. So let's hope there are 2!
695+
expect(await readOutputFile('main.css')).toIncludeCss(
696+
css`
697+
.flex {
698+
display: flex;
699+
}
700+
701+
.font-bold {
702+
font-weight: 700;
703+
}
704+
`
705+
)
706+
707+
return runningProcess.stop()
708+
})
608709
})

src/cli/build/plugin.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,26 @@ export async function createProcessor(args, cliConfigPath) {
328328

329329
return readInput()
330330
.then((css) => processor.process(css, { ...postcssOptions, from: input, to: output }))
331+
.then((result) => {
332+
if (!state.watcher) {
333+
return result
334+
}
335+
336+
env.DEBUG && console.time('Recording PostCSS dependencies')
337+
for (let message of result.messages) {
338+
if (message.type === 'dependency') {
339+
state.contextDependencies.add(message.file)
340+
}
341+
}
342+
env.DEBUG && console.timeEnd('Recording PostCSS dependencies')
343+
344+
// TODO: This needs to be in a different spot
345+
env.DEBUG && console.time('Watch new files')
346+
state.watcher.refreshWatchedFiles()
347+
env.DEBUG && console.timeEnd('Watch new files')
348+
349+
return result
350+
})
331351
.then((result) => {
332352
if (!output) {
333353
process.stdout.write(result.css)

src/cli/build/watching.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export function createWatcher(args, { state, rebuild }) {
6262
extension: path.extname(file).slice(1),
6363
})
6464

65-
chain = chain.then(() => rebuild(changedContent))
65+
chain = chain.then(() => rebuild(changedContent.splice(0)))
6666

6767
return chain
6868
}

0 commit comments

Comments
 (0)