16 Commits
Author SHA1 Message Date
Robin Malfait f7f47f8e98 Rebuild @tailwindcss/turbopack and @tailwindcss/webpack when the input CSS changes (#20582)
This PR fixes an issue where `next dev` with the
`@tailwindcss/turbopack` loader keeps serving the CSS of the previous
edit after you edit the CSS file. Only a restart of the dev server shows
the latest version.

Fixes https://github.com/tailwindlabs/tailwindcss/issues/20581

The loader caches a compiler for each CSS file. It only does a full
rebuild when the mtime of the input file (or of one of its dependencies)
changes. After a save, Turbopack can run the loader two times:

1. With the previous version of the CSS file. The file on disk already
has the new mtime, so we did a full rebuild from the old source, and
stored the new mtime.
2. With the new version of the CSS file. The mtime did not change since
the first call, so we did an incremental build with the stale compiler
of the first call.

The loader registers the folders that it scans as context dependencies,
and the CSS file is in one of them (e.g. `app/`). So one save
invalidates the loader in two ways, and the first run can still get the
previous content of the file.

`@tailwindcss/postcss` had the same problem with Turbopack
(https://github.com/tailwindlabs/tailwindcss/pull/17554), and it
compares the input CSS with the input CSS of the last build since
https://github.com/tailwindlabs/tailwindcss/pull/20310. The loader now
does the same: it stores the source on the cache entry, and does a full
rebuild when the source changes.

`@tailwindcss/turbopack` is a copy of `@tailwindcss/webpack`, so the
webpack loader gets the same fix. With webpack, the problem shows up
when a loader that runs before ours changes the CSS, but not the input
file. For example, `sass-loader` inlines a partial, and you edit that
partial.

The matrix of the integration tests in CI had no `turbopack` entry, so
the tests in `integrations/turbopack` never ran in CI. This PR adds it.

## Test plan

- Added an integration test to `integrations/turbopack/loader.test.ts`.
It edits `app/globals.css` three times during `next dev`, and checks
that the served CSS has each edit. On `main` (with Next.js 16.4.1), the
served CSS still has `.custom-1` after the first edit. With this change,
it passes.
- Added an integration test to `integrations/webpack/loader.test.ts`,
with a loader before `@tailwindcss/webpack` that inlines
`src/partial.css`. In watch mode, it edits that partial. On `main`, the
output keeps `.partial-1`. With this change, it passes.
- Called the built loaders directly, like Turbopack does: first with the
previous source after the file changed on disk, then with the new
source. On `main`, the second call returns the CSS of the previous
version. With this change, each call returns the CSS of the source that
it gets.
- `pnpm run build` passes, and all tests in
`integrations/turbopack/loader.test.ts` and
`integrations/webpack/loader.test.ts` pass.

<sub>Sent by an AI assistant on behalf of @RobinMalfait.</sub>
2026-10-16 13:28:05 +02:00
Robin Malfait c2b24dd15f 4.3.3 (#20334) 2026-07-16 07:21:50 -04:00
Robin Malfait 056a155072 4.3.2 (#20281) 2026-06-29 10:10:00 -04:00
Robin Malfait 8a14a71010 4.3.1 (#20226) 2026-06-12 19:33:35 +02:00
Jiahan ChenandRobin Malfait 982e920df8 Add Rspack optional peer dependency for @tailwindcss/webpack (#20027)
## Summary

This PR makes Rspack support explicit for `@tailwindcss/webpack` by
adding `@rspack/core` as an optional peer dependency alongside
`webpack`.

The loader already works through Rspack's webpack-compatible loader API,
as shown in this runnable example:
https://github.com/rstackjs/rstack-examples/tree/main/rspack/tailwindcss.
The README and package description are updated to document that usage.

## Test plan

No Rspack-specific tests were added. The loader implementation is
unchanged, and the existing webpack loader tests exercise the same
loader API path that Rspack uses, which should cover the relevant
behavior.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-05-23 11:14:48 +02:00
Robin Malfait 588bd7371f 4.3.0 (#20023) 2026-05-08 22:03:59 +02:00
Robin Malfait 3a890c3572 Bump dependencies (#19957)
This PR bumps dependencies in all the packages, typically just bumping
to the latest patch release.


Closes: #19936
Closes: #19917
Closes: #19899
Closes: #19897
Closes: #19845
Closes: #19832
Closes: #19967
Closes: #19968 

## Test plan

1. All tests still pass
2. All integration tests still pass

[ci-all] to verify Linux, Windows and macOS
2026-04-24 21:21:12 +02:00
Robin Malfait 69ad7cc5ec 4.2.4 (#19948) 2026-04-21 14:52:34 +02:00
Robin Malfait 2e3fa490a5 4.2.3 (#19944) 2026-04-20 22:32:52 +02:00
Qingyu WangandRobin Malfait 17d324f896 Fix webpack loader cache key for resource queries (#19723)
<!--

👋 Hey, thanks for your interest in contributing to Tailwind!

**Please ask first before starting work on any significant new
features.**

It's never a fun experience to have your pull request declined after
investing a lot of time and effort into a new feature. To avoid this
from happening, we request that contributors create a discussion to
first discuss any significant new features.

For more info, check out the contributing guide:


https://github.com/tailwindlabs/tailwindcss/blob/main/.github/CONTRIBUTING.md

-->

## Summary

<!--

Provide a summary of the issue and the changes you're making. How does
your change solve the problem?

-->

`@tailwindcss/webpack` currently uses `this.resourcePath` as the cache
key, which ignores the resource query. When the same CSS file is
imported multiple times with different `resourceQuery` values, all of
those imports share a single `CacheEntry`. That means the utilities
discovered for one entry can leak into the CSS output for another entry.

This PR changes the cache key to use `this.resource` (path + query)
instead, while still using `this.resourcePath` for all filesystem work.

## Test plan

<!--

Explain how you tested your changes. Include the exact commands that you
used to verify the change works and include screenshots/screen
recordings of the update behavior in the browser if applicable.

-->

- `pnpm test:integrations -- webpack/loader.test.ts`  
  - Confirms all existing webpack loader integration tests pass.  
- Confirms the new `@tailwindcss/webpack loader isolates cache by
resource including query` test passes, verifying that two entries
importing the same CSS file with different queries produce isolated
outputs (`dist/a.css` only contains `only-a` / `--color-red-500`, and
`dist/b.css` only contains `only-b` / `--color-blue-500`).

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-03-20 16:34:11 +00:00
Robin Malfait d596b0c43d 4.2.2 (#19821) 2026-03-18 11:44:08 -04:00
Robin Malfait 1dce64ee7e 4.2.1 (#19714) 2026-02-23 11:45:12 +01:00
Robin Malfait 1a973557ed update webpack readme to be a bit more consistent with other readmes 2026-02-20 12:04:41 +01:00
Robin Malfait 14083ad9aa use simpler tailwindcss import 2026-02-20 12:03:25 +01:00
Robin MalfaitandAdam Wathan 1b16411919 4.2.0 (#19695)
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2026-02-18 15:45:06 +01:00
Tim NeutkensandRobin Malfait bccf4bbfbd Add @tailwindcss/webpack loader for Tailwind CSS v4 (#19610)
## Summary

This PR adds a new `@tailwindcss/webpack` package that provides a
dedicated webpack loader for Tailwind CSS v4. This loader works with
both standard webpack and Turbopack's webpack loader compatibility
layer.

### Why a dedicated loader?

The current webpack integration uses `postcss-loader` +
`@tailwindcss/postcss`. While this works, a dedicated loader:

- **Eliminates PostCSS as a middleman** - works directly with CSS
strings (no AST conversions)
- **Simpler and more efficient** - follows the same pattern as
`@tailwindcss/vite`
- **Better for Turbopack** - gives direct control over dependency
reporting via webpack's loader API

### How it works

The loader mirrors the Vite plugin's approach:

1. Uses `compile()` from `@tailwindcss/node` to parse CSS and resolve
`@apply` directives
2. Uses `Scanner` from `@tailwindcss/oxide` to scan content files for
utility candidates
3. Reports dependencies via `this.addDependency()` and
`this.addContextDependency()`
4. Optionally optimizes output with Lightning CSS

### Usage

```javascript
// webpack.config.js
module.exports = {
  module: {
    rules: [
      {
        test: /.css$/i,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader',
          '@tailwindcss/webpack',  // No PostCSS needed!
        ],
      },
    ],
  },
}
```

### Options

- `base` - The base directory to scan for class candidates (defaults to
`process.cwd()`)
- `optimize` - Whether to optimize/minify the output CSS (defaults to
`true` in production)

### Files added

- `packages/@tailwindcss-webpack/` - New package
  - `src/index.ts` - Main loader implementation
  - `src/index.cts` - CommonJS entry point for webpack compatibility
  - `package.json`, `tsconfig.json`, `tsup.config.ts`, `README.md`
- `integrations/webpack/loader.test.ts` - Integration tests
- `integrations/utils.ts` - Added webpack override for transitive
dependencies

### Test plan

- [x] Build test - verifies basic compilation
- [x] Watch test - verifies HMR when adding new Tailwind classes
- [x] `@apply` test - verifies `@apply` directives work correctly
- [x] Optimization test - verifies minification works

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2026-01-29 14:16:31 +00:00