From d7393f95bc40d6f995e1b3613776c9418e73a839 Mon Sep 17 00:00:00 2001 From: Philipp Spiess Date: Wed, 28 Aug 2024 17:19:33 +0200 Subject: [PATCH] Support vite build --watch mode --- integrations/vite/index.test.ts | 240 ++++++++++++------------ packages/@tailwindcss-vite/src/index.ts | 6 + 2 files changed, 124 insertions(+), 122 deletions(-) diff --git a/integrations/vite/index.test.ts b/integrations/vite/index.test.ts index 5d7b08af6..26f5e9bdc 100644 --- a/integrations/vite/index.test.ts +++ b/integrations/vite/index.test.ts @@ -219,135 +219,131 @@ import { }, ) - // test( - // 'watch mode', - // { - // fs: { - // 'package.json': json`{}`, - // 'pnpm-workspace.yaml': yaml` - // # - // packages: - // - project-a - // `, - // 'project-a/package.json': json` - // { - // "type": "module", - // "dependencies": { - // "@tailwindcss/vite": "workspace:^", - // "tailwindcss": "workspace:^" - // }, - // "devDependencies": { - // "vite": "^5.3.5" - // } - // } - // `, - // 'project-a/vite.config.ts': ts` - // import tailwindcss from '@tailwindcss/vite' - // import { defineConfig } from 'vite' + test.only( + 'watch mode', + { + fs: { + 'package.json': json`{}`, + 'pnpm-workspace.yaml': yaml` + # + packages: + - project-a + `, + 'project-a/package.json': json` + { + "type": "module", + "dependencies": { + "@tailwindcss/vite": "workspace:^", + "tailwindcss": "workspace:^" + }, + "devDependencies": { + "vite": "^5.3.5" + } + } + `, + 'project-a/vite.config.ts': ts` + import tailwindcss from '@tailwindcss/vite' + import { defineConfig } from 'vite' - // export default defineConfig({ - // build: { cssMinify: false }, - // plugins: [tailwindcss()], - // }) - // `, - // 'project-a/index.html': html` - // - // - // - // - //
Hello, world!
- // - // `, - // 'project-a/src/index.css': css` - // @import 'tailwindcss/theme' theme(reference); - // @import 'tailwindcss/utilities'; - // @source '../../project-b/src/**/*.js'; - // `, - // 'project-b/src/index.js': js` - // const className = "content-['project-b/src/index.js']" - // module.exports = { className } - // `, - // }, - // }, - // async ({ root, spawn, fs }) => { - // await spawn(`pnpm vite build --watch`, { - // cwd: path.join(root, 'project-a'), - // }) + export default defineConfig({ + build: { cssMinify: false }, + plugins: [tailwindcss()], + }) + `, + 'project-a/index.html': html` + + + + +
Hello, world!
+ + `, + 'project-a/src/index.css': css` + @import 'tailwindcss/theme' theme(reference); + @import 'tailwindcss/utilities'; + @source '../../project-b/src/**/*.js'; + `, + 'project-b/src/index.js': js` + const className = "content-['project-b/src/index.js']" + module.exports = { className } + `, + }, + }, + async ({ root, spawn, fs }) => { + await spawn(`pnpm vite build --watch`, { + cwd: path.join(root, 'project-a'), + }) - // let filename = '' - // await retryAssertion(async () => { - // let files = await fs.glob('project-a/dist/**/*.css') - // expect(files).toHaveLength(1) - // filename = files[0][0] - // }) + let filename = '' + await retryAssertion(async () => { + let files = await fs.glob('project-a/dist/**/*.css') + expect(files).toHaveLength(1) + filename = files[0][0] + }) - // await fs.expectFileToContain(filename, [candidate`underline`]) + await fs.expectFileToContain(filename, [candidate`underline`]) - // await new Promise((resolve) => setTimeout(resolve, 1000)) + await new Promise((resolve) => setTimeout(resolve, 1000)) - // // Updates are additive and cause new candidates to be added. - // await fs.write( - // 'project-a/index.html', - // html` - // - // - // - // - //
Hello, world!
- // - // `, - // ) - // await retryAssertion(async () => { - // let files = await fs.glob('project-a/dist/**/*.css') - // let filenames = files.map(([filename]) => filename) - // // Expect a rebuild to have a different .css hash - // expect(filenames).not.toContain(filename) - // expect(filenames).toHaveLength(1) - // filename = filenames[0] - // }) - // await fs.expectFileToContain(filename, [candidate`underline`, candidate`m-2`]) + // Updates are additive and cause new candidates to be added. + await fs.write( + 'project-a/index.html', + html` + + + + +
Hello, world!
+ + `, + ) + await retryAssertion(async () => { + let files = await fs.glob('project-a/dist/**/*.css') + expect(files).toHaveLength(1) + let [, css] = files[0] + expect(css).toContain(candidate`underline`) + expect(css).toContain(candidate`m-2`) + }) - // // Manually added `@source`s are watched and trigger a rebuild - // await fs.write( - // 'project-b/src/index.js', - // js` - // const className = "[.changed_&]:content-['project-b/src/index.js']" - // module.exports = { className } - // `, - // ) - // await fs.expectFileToContain(filename, [ - // candidate`underline`, - // candidate`m-2`, - // candidate`[.changed_&]:content-['project-b/src/index.js']`, - // ]) + // Manually added `@source`s are watched and trigger a rebuild + await fs.write( + 'project-b/src/index.js', + js` + const className = "[.changed_&]:content-['project-b/src/index.js']" + module.exports = { className } + `, + ) + await retryAssertion(async () => { + let files = await fs.glob('project-a/dist/**/*.css') + expect(files).toHaveLength(1) + let [, css] = files[0] + expect(css).toContain(candidate`underline`) + expect(css).toContain(candidate`m-2`) + expect(css).toContain(candidate`[.changed_&]:content-['project-b/src/index.js']`) + }) - // // After updates to the CSS file, all previous candidates should still be in - // // the generated CSS - // await fs.write( - // 'project-a/src/index.css', - // css` - // ${await fs.read('project-a/src/index.css')} + // After updates to the CSS file, all previous candidates should still be in + // the generated CSS + await fs.write( + 'project-a/src/index.css', + css` + ${await fs.read('project-a/src/index.css')} - // .red { - // color: red; - // } - // `, - // ) - // await retryAssertion(async () => { - // let files = await fs.glob('project-a/dist/**/*.css') - // let filenames = files.map(([filename]) => filename) - // // Expect a rebuild to have a different .css hash - // expect(filenames).not.toContain(filename) - // expect(filenames).toHaveLength(1) - // filename = filenames[0] - // }) - // await fs.expectFileToContain(filename, [ - // candidate`red`, - // candidate`underline`, - // candidate`m-2`, - // candidate`[.changed_&]:content-['project-b/src/index.js']`, - // ]) - // }, - // ) + .red { + color: red; + } + `, + ) + await retryAssertion(async () => { + let files = await fs.glob('project-a/dist/**/*.css') + expect(files).toHaveLength(1) + let [, css] = files[0] + expect(css).toContain(candidate`underline`) + expect(css).toContain(candidate`m-2`) + expect(css).toContain(candidate`[.changed_&]:content-['project-b/src/index.js']`) + expect(css).toContain(candidate`red`) + }) + }, + ) }) }) diff --git a/packages/@tailwindcss-vite/src/index.ts b/packages/@tailwindcss-vite/src/index.ts index 235575b69..6c09da0d7 100644 --- a/packages/@tailwindcss-vite/src/index.ts +++ b/packages/@tailwindcss-vite/src/index.ts @@ -333,6 +333,12 @@ export default function tailwindcss(): Plugin[] { apply: 'build', enforce: 'pre', + buildStart() { + for (let [, file] of Object.entries(cssModules)) { + file.handled = false + } + }, + async transform(src, id) { if (!isTailwindCssFile(id, src)) return onFileChange(id)