58 Commits

Author SHA1 Message Date
Philipp Spiess
2327e68bc7
Prepare v4.0.0-alpha.29 release (#14761) 2024-10-23 15:30:26 +02:00
Jordan Pittman
19de55792f
Ensure changes to the input CSS file result in a full rebuild (#14744)
Fixes #14726

I think we broke this when we changed core so that it can handle
`@import "…"` in CSS.
2024-10-21 20:29:33 +00:00
Adam Wathan
b701ed6916
Prepare v4.0.0-alpha.28 release (#14709)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-17 17:03:28 -04:00
Philipp Spiess
a75152d162
Release v4.0.0-alpha.27 (#14671) 2024-10-15 10:28:34 +00:00
Philipp Spiess
8b0d22435c
Fix CLI client crash when a file is removed before we process the change notification (#14616)
Fixes #14613

Don't crash when trying to read the modification time of a file that
might already be deleted.

Note: This fix is purely theoretical right now as I wasn't able to
reproduce the issue yet.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-09 14:56:08 +00:00
Robin Malfait
39e108d5f5
release v4.0.0-alpha.26 2024-10-03 16:39:59 +02:00
Robin Malfait
35b84cc313
Improve @tailwindcss/postcss performance for initial builds (#14565)
This PR improves the performance of the `@tailwindcss/postcss` plugin.
Before this change we created 2 compiler instances instead of a single
one. On a project where a `tailwindcss.config.ts` file is used, this
means that the timings look like this:

```
[@tailwindcss/postcss] Setup compiler: 137.525ms
⋮
[@tailwindcss/postcss] Setup compiler: 43.95ms
```

This means that with this small change, we can easily shave of ~50ms for
initial PostCSS builds.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-10-03 16:21:54 +02:00
Robin Malfait
ab82efab7d
Expose timing information in debug mode (#14553)
This PR exposes when using the the `DEBUG` environment variable. This
follows the `DEBUG` conventions where:

- `DEBUG=1`
- `DEBUG=true`
- `DEBUG=*`
- `DEBUG=tailwindcss`

Will enable the debug information, but when using:

- `DEBUG=0`
- `DEBUG=false`
- `DEBUG=-tailwindcss`

It will not.

This currently only exposes some timings related to:

1. Scanning for candidates
2. Building the CSS
3. Optimizing the CSS

We can implement a more advanced version of this where we also expose
more fine grained information such as the files we scanned, the amount
of candidates we found and so on. But I believe that this will be enough
to start triaging performance related issues.
2024-09-30 14:39:21 +00:00
Philipp Spiess
89f0047c0d
CLI: Use the right base when loading files from stdin (#14522)
Fixes #14521

When using the CLI to read files from `stdin` like this:

```bash
npx tailwindcss  --input=- -o bar.css < foo.css
```

We need to set the `base` path to be the current working directory
(`process.cwd()`). However, `cwd()` already _is_ a directory and calling
`dirname()` on it did go to the parent directory _which might not have
the `tailwindcss` dependency installed.
2024-09-26 12:32:46 +02:00
Robin Malfait
c094fadbbc
Release v4.0.0-alpha.25 (#14507) 2024-09-24 17:03:00 +00:00
Philipp Spiess
79794744a9
Resolve @import in core (#14446)
This PR brings `@import` resolution into Tailwind CSS core. This means
that our clients (PostCSS, Vite, and CLI) no longer need to depend on
`postcss` and `postcss-import` to resolve `@import`. Furthermore this
simplifies the handling of relative paths for `@source`, `@plugin`, or
`@config` in transitive CSS files (where the relative root should always
be relative to the CSS file that contains the directive). This PR also
fixes a plugin resolution bug where non-relative imports (e.g. directly
importing node modules like `@plugin '@tailwindcss/typography';`) would
not work in CSS files that are based in a different npm package.

### Resolving `@import`

The core of the `@import` resolution is inside
`packages/tailwindcss/src/at-import.ts`. There, to keep things
performant, we do a two-step process to resolve imports. Imagine the
following input CSS file:

```css
@import "tailwindcss/theme.css";
@import "tailwindcss/utilities.css";
```

Since our AST walks are synchronous, we will do a first traversal where
we start a loading request for each `@import` directive. Once all loads
are started, we will await the promise and do a second walk where we
actually replace the AST nodes with their resolved stylesheets. All of
this is recursive, so that `@import`-ed files can again `@import` other
files.

The core `@import` resolver also includes extensive test cases for
[various combinations of media query and supports conditionals as well
als layered
imports](https://developer.mozilla.org/en-US/docs/Web/CSS/@import).

When the same file is imported multiple times, the AST nodes are
duplicated but duplicate I/O is avoided on a per-file basis, so this
will only load one file, but include the `@theme` rules twice:

```css
@import "tailwindcss/theme.css";
@import "tailwindcss/theme.css";
```

### Adding a new `context` node to the AST

One limitation we had when working with the `postcss-import` plugin was
the need to do an additional traversal to rewrite relative `@source`,
`@plugin`, and `@config` directives. This was needed because we want
these paths to be relative to the CSS file that defines the directive
but when flattening a CSS file, this information is no longer part of
the stringifed CSS representation. We worked around this by rewriting
the content of these directives to be relative to the input CSS file,
which resulted in added complexity and caused a lot of issues with
Windows paths in the beginning.

Now that we are doing the `@import` resolution in core, we can use a
different data structure to persist this information. This PR adds a new
`context` node so that we can store arbitrary context like this inside
the Ast directly. This allows us to share information with the sub tree
_while doing the Ast walk_.

Here's an example of how the new `context` node can be used to share
information with subtrees:

```ts
const ast = [
  rule('.foo', [decl('color', 'red')]),
  context({ value: 'a' }, [
    rule('.bar', [
      decl('color', 'blue'),
      context({ value: 'b' }, [
        rule('.baz', [decl('color', 'green')]),
      ]),
    ]),
  ]),
]

walk(ast, (node, { context }) => {
  if (node.kind !== 'declaration') return
  switch (node.value) {
    case 'red':   assert(context.value === undefined)
    case 'blue':  assert(context.value === 'a')
    case 'green': assert(context.value === 'b')
  }
})
```

In core, we use this new Ast node specifically to persist the `base`
path of the current CSS file. We put the input CSS file `base` at the
root of the Ast and then overwrite the `base` on every `@import`
substitution.

### Removing the dependency on `postcss-import`

Now that we support `@import` resolution in core, our clients no longer
need a dependency on `postcss-import`. Furthermore, most dependencies
also don't need to know about `postcss` at all anymore (except the
PostCSS client, of course!).

This also means that our workaround for rewriting `@source`, the
`postcss-fix-relative-paths` plugin, can now go away as a shared
dependency between all of our clients. Note that we still have it for
the PostCSS plugin only, where it's possible that users already have
`postcss-import` running _before_ the `@tailwindcss/postcss` plugin.

Here's an example of the changes to the dependencies for our Vite client
 :

<img width="854" alt="Screenshot 2024-09-19 at 16 59 45"
src="https://github.com/user-attachments/assets/ae1f9d5f-d93a-4de9-9244-61af3aff1237">

### Performance

Since our Vite and CLI clients now no longer need to use `postcss` at
all, we have also measured a significant improvement to the initial
build times. For a small test setup that contains only a hand full of
files (nothing super-complex), we measured an improvement in the
**3.5x** range:

<img width="1334" alt="Screenshot 2024-09-19 at 14 52 49"
src="https://github.com/user-attachments/assets/06071fb0-7f2a-4de6-8ec8-f202d2cc78e5">

The code for this is in the commit history if you want to reproduce the
results. The test was based on the Vite client.

### Caveats

One thing to note is that we previously relied on finding specific
symbols in the input CSS to _bail out of Tailwind processing
completely_. E.g. if a file does not contain a `@tailwind` or `@apply`
directive, it can never be a Tailwind file.

Since we no longer have a string representation of the flattened CSS
file, we can no longer do this check. However, the current
implementation was already inconsistent with differences on the allowed
symbol list between our clients. Ideally, Tailwind CSS should figure out
wether a CSS file is a Tailwind CSS file. This, however, is left as an
improvement for a future API since it goes hand-in-hand with our planned
API changes for the core `tailwindcss` package.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-09-23 17:05:55 +02:00
Philipp Spiess
2ef87ab7fb
Release v4.0.0-alpha.24 (#14395) 2024-09-12 16:10:56 +02:00
Robin Malfait
af774e8f24
Improve the CLI output when nothing changed (#14351)
When we observe that no new candidates were found, then we can return
early because nothing really changed. There is also no need to
re-optimize (use Lightning CSS) in this case.

But this had a side effect that when no new candidates were detected,
that you didn't see any output either. This feels like nothing is
working from a DX perspective.

Typically you are changing things, so it's not really a problem. But the
moment you use a class that already existed (e.g.: in another file) you
also don't get any output because we have a shared cache.

This PR solves that by always showing the output. But it still doesn't
write to disk if nothing changed.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-09-05 17:00:57 -04:00
Jordan Pittman
15d1714c33 v4.0.0-alpha.23 2024-09-05 10:43:07 -04:00
Adam Wathan
d9558bbc4c v4.0.0-alpha.22 2024-09-04 15:50:57 -04:00
Philipp Spiess
a1d56d8e24
Ensure content globs defined in @config files are relative to that file (#14314)
When you configure custom content globs inside an `@config` file, we
want to tread these globs as being relative to that config file and not
the CSS file that requires the content file. A config can be used by
multiple CSS configs.

---------

Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-09-03 16:54:08 +02:00
Adam Wathan
dcfaaac8f6
Prepare v4.0.0-alpha.21 (#14313)
<!--

👋 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 an issue to first
discuss any significant new features. This includes things like adding
new utilities, creating new at-rules, or adding new component examples
to the documentation.


https://github.com/tailwindcss/tailwindcss/blob/master/.github/CONTRIBUTING.md

-->

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-02 15:43:28 -04:00
Jordan Pittman
52012d90d7
Support loading config files via @config (#14239)
In Tailwind v4 the CSS file is the main entry point to your project and
is generally configured via `@theme`. However, given that all v3
projects were configured via a `tailwind.config.js` file we definitely
need to support those. This PR adds support for loading existing
Tailwind config files by adding an `@config` directive to the CSS —
similar to how v3 supported multiple config files except that this is
now _required_ to use a config file.

You can load a config file like so:

```
@import "tailwindcss";
@config "./path/to/tailwind.config.js";
```

A few notes:
- Both CommonJS and ESM config files are supported (loaded directly via
`import()` in Node)
- This is not yet supported in Intellisense or Prettier — should
hopefully land next week
- TypeScript is **not yet** supported in the config file — this will be
handled in a future PR.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-09-02 18:03:16 +02:00
Philipp Spiess
d9e3fd613b
Add standalone CLI (#14270)
This PR adds a new standalone client: A single-binary file that you can
use to run Tailwind v4 without having a node setup. To make this work we
use Bun's single-binary build which can properly package up native
modules and the bun runtime for us so we do not have to rely on any
expand-into-tmp-folder-at-runtime workarounds.

When running locally, `pnpm build` will now standalone artifacts inside
`packages/@tailwindcss-standalone/dist`. Note that since we do not build
Oxide for other environments in the local setup, you won't be able to
use the standalone artifacts for other platforms in local dev mode.

Unfortunately Bun does not have support for Windows ARM builds yet but
we found that using the `bun-baseline` runtime for Windows x64 would
make the builds work fine in ARM emulation mode:

![Screenshot
windows](https://github.com/user-attachments/assets/5b39387f-ec50-4757-9469-19b98e43162d)


Some Bun related issues we faced and worked around:

- We found that the regular Windows x64 build of `bun` does not run on
Windows ARM via emulation. Instead, we have to use the `bun-baseline`
builds which emulate correctly.

- When we tried to bundle artifacts with [embed
directories](https://bun.sh/docs/bundler/executables#embed-directories),
node binary dependencies were no longer resolved correctly even though
they would still be bundled and accessible within the [`embeddedFiles`
list](https://bun.sh/docs/bundler/executables#listing-embedded-files).
We worked around this by using the `import * as from ... with { type:
"file" };` and patching the resolver we use in our CLI.
  
  
- If you have an import to a module that is used as a regular import
_and_ a `with { type: "file" }`, it will either return the module in
both cases _or_ the file path when we would expect only the `with {
type: "file" }` import to return the path. We do read the Tailwind CSS
version via the file system and `require.resolve()` in the CLI and via
`import * from './package.json'` in core and had to work around this by
patching the version resolution in our CLI.
 
  ```ts
  import packageJson from "./package.json"
  import packageJsonPath from "./package.json" with {type: "file"}
  
  // We do not expect these to be equal
  packageJson === packageJsonPath 
  ```
- We can not customize the app icon used for Windows `.exe` builds
without decompiling the binary. For now we will leave the default but
one workaround is to [use tools like
ResourceHacker](698d9c4bd1)
to decompile the binary first.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-09-02 15:23:46 +02:00
Philipp Spiess
d5f563b746
Prepare v4.0.0-alpha.20 (#14244)
Prepare next `4.0.0-alpha.20` release
2024-08-23 15:51:53 +02:00
Robin Malfait
a902128640
Improve Oxide scanner API (#14187)
This PR updates the API for interacting with the Oxide API. Until now,
we used the name `scanDir(…)` which is fine, but we do way more work
right now.

We now have features such as:

1. Auto source detection (can be turned off, e.g.: `@tailwindcss/vite`
doesn't need it)
2. Scan based on `@source`s found in CSS files
3. Do "incremental" rebuilds (which means that the `scanDir(…)` result
was stateful).

To solve these issues, this PR introduces a new `Scanner` class where
you can pass in the `detectSources` and `sources` options. E.g.:

```ts
let scanner = new Scanner({
  // Optional, omitting `detectSources` field disables automatic source detection
  detectSources: { base: __dirname }, 

  // List of glob entries to scan. These come from `@source` directives in CSS.
  sources: [
    { base: __dirname, pattern: "src/**/*.css" },
    // …
  ],
});
```

The scanner object has the following API:

```ts
export interface ChangedContent {
  /** File path to the changed file */
  file?: string
  /** Contents of the changed file */
  content?: string
  /** File extension */
  extension: string
}
export interface DetectSources {
  /** Base path to start scanning from */
  base: string
}
export interface GlobEntry {
  /** Base path of the glob */
  base: string
  /** Glob pattern */
  pattern: string
}
export interface ScannerOptions {
  /** Automatically detect sources in the base path */
  detectSources?: DetectSources
  /** Glob sources */
  sources?: Array<GlobEntry>
}
export declare class Scanner {
  constructor(opts: ScannerOptions)
  scan(): Array<string>
  scanFiles(input: Array<ChangedContent>): Array<string>
  get files(): Array<string>
  get globs(): Array<GlobEntry>
}
```

The `scanFiles(…)` method is used for incremental rebuilds. It takes the
`ChangedContent` array for all the new/changes files. It returns whether
we scanned any new candidates or not.

Note that the `scanner` object is stateful, this means that we don't
have to track candidates in a `Set` anymore. We can just call
`getCandidates()` when we need it.

This PR also removed some unused code that we had in the `scanDir(…)`
function to allow for sequential or parallel `IO`, and sequential or
parallel `Parsing`. We only used the same `IO` and `Parsing` strategies
for all files, so I just got rid of it.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-08-16 15:05:42 +02:00
Robin Malfait
f5f91ce9de
Prepare v4.0.0-alpha.19 (#14162)
Prepare next `4.0.0-alpha.19` release
2024-08-09 17:58:30 +02:00
Robin Malfait
d223112162
Bump dependencies (#14160)
This PR bumps dependencies

We also make some dependencies `catalog:` dependencies, which allows us
to keep
the version in sync. E.g.: `lightningcss` and `@types/node`.

Bumped `turbo` to the latest version + enabled the new UI

Fixed a bug in the tests now that `lightningcss` outputs the correct
value.
2024-08-09 16:12:24 +02:00
Philipp Spiess
921b4b673b
Use import to load plugins (#14132)
Alternative to #14110

This PR changes the way how we load plugins to be compatible with ES6
async `import`s. This allows us to load plugins even inside the browser
but it comes at a downside: We now have to change the `compile` API to
return a `Promise`...

So most of this PR is rewriting all of the call sites of `compile` to
expect a promise instead of the object.

---------

Co-authored-by: Jordan Pittman <jordan@cryptica.me>
2024-08-08 11:49:06 -04:00
Robin Malfait
541d84a3bb
Add @source support (#14078)
This PR is an umbrella PR where we will add support for the new
`@source` directive. This will allow you to add explicit content glob
patterns if you want to look for Tailwind classes in other files that
are not automatically detected yet.

Right now this is an addition to the existing auto content detection
that is automatically enabled in the `@tailwindcss/postcss` and
`@tailwindcss/cli` packages. The `@tailwindcss/vite` package doesn't use
the auto content detection, but uses the module graph instead.

From an API perspective there is not a lot going on. There are only a
few things that you have to know when using the `@source` directive, and
you probably already know the rules:

1. You can use multiple `@source` directives if you want.
2. The `@source` accepts a glob pattern so that you can match multiple
files at once
3. The pattern is relative to the current file you are in
4. The pattern includes all files it is matching, even git ignored files
1. The motivation for this is so that you can explicitly point to a
`node_modules` folder if you want to look at `node_modules` for whatever
reason.
6. Right now we don't support negative globs (starting with a `!`) yet,
that will be available in the near future.

Usage example:

```css
/* ./src/input.css */
@import "tailwindcss";
@source "../laravel/resources/views/**/*.blade.php";
@source "../../packages/monorepo-package/**/*.js";
```

It looks like the PR introduced a lot of changes, but this is a side
effect of all the other plumbing work we had to do to make this work.
For example:

1. We added dedicated integration tests that run on Linux and Windows in
CI (just to make sure that all the `path` logic is correct)
2. We Have to make sure that the glob patterns are always correct even
if you are using `@import` in your CSS and use `@source` in an imported
file. This is because we receive the flattened CSS contents where all
`@import`s are inlined.
3. We have to make sure that we also listen for changes in the files
that match any of these patterns and trigger a rebuild.

PRs:

- [x] https://github.com/tailwindlabs/tailwindcss/pull/14063
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14085
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14079
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14067
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14076
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14080
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14127
- [x] https://github.com/tailwindlabs/tailwindcss/pull/14135

Once all the PRs are merged, then this umbrella PR can be merged. 

> [!IMPORTANT]  
> Make sure to merge this without rebasing such that each individual PR
ends up on the main branch.

---------

Co-authored-by: Philipp Spiess <hello@philippspiess.com>
Co-authored-by: Jordan Pittman <jordan@cryptica.me>
Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-08-07 16:38:44 +02:00
Philipp Spiess
a2159e80f5
Add Windows CI (#14065)
This PR changes the GitHub action workflow for V4 to start running all
unit tests and build on both Ubuntu (our current default) _and_ Windows.
This is to ensure we catch issues with paths and other Windows-specific
things sooner. It does, however, not replace testing on Windows.
2024-07-29 16:50:06 +02:00
Adam Wathan
50a6a37dc9
Prepare for v4.0.0-alpha.18 release (#14057)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-07-25 10:19:13 -04:00
Adam Wathan
54474086c8
Add support for basic addVariant plugins with new @plugin directive (#13982)
* Add basic `addVariant` plugin support

* Return early

* Load plugins right away instead later

* Use correct type for variant name

* Preliminary support for addVariant plugins in PostCSS plugin

* Add test for compounding plugin variants

* Add basic `loadPlugin` support to Vite plugin

* Add basic `loadPlugin` support to CLI

* add `io.ts` for integrations

* use shared `loadPlugin` from `tailwindcss/io`

* add `tailwindcss-test-utils` to `@tailwindcss/cli` and `@tailwindcss/vite`

* only add `tailwindcss-test-utils` to `tailwindcss` as a dev dependency

Because `src/io.ts` is requiring the plugin.

* move `tailwindcss-test-utils` to `@tailwindcss/postcss `

This is the spot where we actually need it.

* use newer pnpm version

* Duplicate loadPlugin implementation instead of exporting io file

* Remove another io reference

* update changelog

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-07-11 09:47:26 -04:00
Robin Malfait
06e96e0767
Prep next release: 4.0.0-alpha.17 (#13951)
* bump to version `4.0.0-alpha.17`

* update changelog
2024-07-04 19:08:10 +02:00
Robin Malfait
c711903af5
Prepare next alpha release: 4.0.0-alpha.16 (#13810)
* bump version to 4.0.0-alpha.16

* update changelog
2024-06-07 18:38:44 +02:00
Robin Malfait
2fedbe0194
Bump dependencies (#13741)
* bump dependencies

* update tests to reflect Lightning CSS change
2024-05-25 14:43:59 +02:00
Robin Malfait
0e92310caf
Bump dependencies (#13738)
* run `pnpm update --recursive`

* update tests to reflect lightningcss bump

It looks like it's mainly (re-)ordering properties. Not 100% sure why
though.
2024-05-24 15:07:44 +02:00
Robin Malfait
5e737d8587
4.0.0-alpha.15 (#13658) 2024-05-08 19:26:59 +02:00
Robin Malfait
ce0a7347da
4.0.0-alpha.14 (#13487) 2024-04-09 20:55:54 +02:00
Adam Wathan
2719903e56 Update versions for alpha.13 2024-04-04 18:03:36 -04:00
Robin Malfait
34fea0e3d3
4.0.0-alpha.12 (#13448) 2024-04-04 17:43:02 +02:00
Aaron Adams
be94e21136
Correct repository fields in package.json files (#13416) 2024-03-31 15:20:53 -04:00
Jordan Pittman
855cd94ff0
Prepare next release: 4.0.0-alpha.11 (#13382)
* bump versions to `4.0.0-alpha.11`

* Update changelog

* Update changelog

* Update changelog

* Update changelog
2024-03-27 13:32:10 -04:00
Robin Malfait
c815221249
Ensure build command is executed when using --output instead of -o (#13369) 2024-03-27 16:10:55 +01:00
Robin Malfait
8840019efa
Prepare next release: 4.0.0-alpha.10 (#13281)
* bump versions to `4.0.0-alpha.10`

* update changelog

* Update changelog

---------

Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-03-21 13:32:03 -04:00
Robin Malfait
44394b164a
Prepare 4.0.0-alpha.9 release (#13231)
* update changelog

* bump versions to `4.0.0-alpha.9`

* move the optimizeCss change to `Changed`
2024-03-13 13:11:06 -04:00
Robin Malfait
0ee3508179
Move optimizeCss to the packages where it's used (#13230)
* add `@tailwindcss/optimize` as a separate package

* remove lightningcss from `tailwindcss`

* import `optimizeCss` from `@tailwindcss/optimize`

* ensure we use `src/` files in development

* move `devDependencies` after `dependencies`

Just for consistency

* inline `optimizeCss` in leaf packages

Instead of introducing a custom `@tailwindcss/optimize` package

* update changelog

* fix changelog
2024-03-13 17:25:16 +01:00
Adam Wathan
65f6f7c1ca
Prepare alpha.8 release (#13203)
Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-03-11 15:10:21 -04:00
Robin Malfait
a458e5ddda
Add incremental rebuilds to @tailwindcss/cli (#13169)
* ensure the root CSS file part of the `cssImportPaths`

* add incremental rebuilds to `@tailwindcss/cli`

* update changelog
2024-03-11 14:32:41 -04:00
Robin Malfait
d230f2e13b
Improve incremental builds (#13168)
* ensure we don't crash on deleted files

* change return type of `compile` to include a `rebuild()` function

This will allow us in the future to perform incremental rebuilds after
the initial rebuild. This is purely the API change so that we can
prepare all the call sites to use this new API.

* set `@tailwind utilities` nodes

Instead of replacing the node that represents the `@tailwind utilities`
with the generated AST nodes from the rawCandidates, we will set the
nodes of the `@tailwind utilities` rule to the AST nodes instead.

This way we dont' have to remove and replace the `@tailwind utilities`
rule with `n` new nodes. This will later allow us to track the
`@tailwindcss utilities` rule itself and update its `nodes` for
incremental rebuilds.

This also requires a small change to the printer where we now need to
print the children of the `@tailwind utilities` rule. Note: we keep the
same `depth` as-if the `@tailwindcss utilities` rule was not there.
Otherwise additional indentation would be present.

* move sorting to the `ast.sort()` call

This will allow us to keep sorting AST nodes in a single spot.

* move parser functions to the `DesignSystem`

This allows us to put all the parsers in the `DesignSystem`, this allows
us to scope the parsers to the current design system (the current theme,
current utility values and variants).

The implementation of these parsers are also using a `DefaultMap`
implementation. This allows us to make use of caching and only parse a
candidate, parse a variant or compile AST nodes for a given raw
candidate once if we've already done this work in the past.

Again, this is scoped to the `DesignSystem` itself. This means that if
the corresponding theme changes, then we will create a new
`DesignSystem` entirely and the caches will be garbage collected. This
is important because a candidate like `bg-primary` can be invalid in
`DesignSystem` A, but can be valid in `DesignSystem` B and vice versa.

* ensure we sort variants alphabetically by root

For incremental rebuilds we don't know all the used variants upfront,
which means that we can't sort them upfront either (what we used to do).

This code now allows us to sort the variants deterministically when
sorting the variants themselves instead of relying on the fact that they
used to be sorted before.

The sort itself could change slightly compared to the previous
implementation (especially when you used stacked variants in your
candidates), but it will still be deterministic.

* replace `localeCompare` comparisons

Use cheaper comparisons than `localeCompare` when comparing 2 strings.
We currently don't care if it is 100% correctly sorted, but we just want
consistent sorting. This is currently faster compared to
`localeCompare`.

Another benefit is that `localeCompare` could result in
non-deterministic results if the CSS was generated on 2 separate
computers where the `locale` is different.

We could solve that by adding a dedicated locale, but it would still be
slower compared to this.

* track invalid candidates

When an incoming raw candidates doesn't produce any output, then we can
mark it as an invalid candidate. This will allow us to reduce the amount
of candidates to handle in incremental rebuilds.

* add initial incremental rebuild implementation

This includes a number of steps:

1. Track the `@tailwind utilities` rule, so that we can adjust its nodes
   later without re-parsing the full incoming CSS.
2. Add the new incoming raw candidates to the existing set of
   candidates.
3. Parse the merged set to `compileCandidates` (this can accept any
   `Iterable<string>`, which means `string[]`, `Set<string>`, ...)
4. Get the new AST nodes, update the `@tailwind utilities` rule's nodes
   and re-print the AST to CSS.

* improvement 1: ignore known invalid candidates

This will reduce the amount of candidates to handle. They would
eventually be skipped anyway, but now we don't even have to re-parse
(and hit a cache) at all.

* improvement 2: skip work, when generated AST is the same

Currently incremental rebuilds are additive, which means that we are not
keeping track if we should remove CSS again in development.

We can exploit this information, because now we can quickly check the
amoutn of generated AST nodes.

- If they are the same then nothing new is generated — this means that
  we can re-use the previous compiled CSS. We don't even have to
  re-print the AST because we already did do that work in the past.
- If there are more AST nodes, something new is generated — this means
  that we should update the `@tailwind utilities` rule and re-print the
  CSS. We can store the result for future incremental rebuilds.

* improvement 3: skip work if no new candidates are detected

- We already know a set of candidates from previous runs.
- We also already know a set of candidates that are invalid and don't
  produce anything.

This means that an incremental rebuild could give us a new set of
candidates that either already exist or are invalid.

If nothing changes, then we can re-use the compiled CSS.

This actually happens more often than you think, and the bigger your
project is the better this optimization will be.

For example:

```
// Imagine file A exists:
<div class="flex items-center justify-center"></div>
<button class="text-red-500">Delete</button>
```

```
// Now you add a second file B:
<div class="text-red-500 flex"></div>
```

You just created a brand new file with a bunch of HTML elements and
classes, yet all of the candidates in file B already exist in file A, so
nothing changes to the actual generated CSS.

Now imagine the other hundreds of files that already contain hundreds of
classes.

The beauty of this optimization is two-fold:

- On small projects, compiling is very fast even without this check.
  This means it is performant.
- On bigger projects, we will be able to re-use existing candidates.
  This means it stays performant.

* remove `getAstNodeSize`

We can move this up the tree and move it to the `rebuild` function
instead.

* remove invalid candidate tracking from `DesignSystem`

This isn't used anywhere but only in the `rebuild` of the compile step.
This allows us to remove it entirely from core logic, and move it up the
chain where it is needed.

* replace `throwOnInvalidCandidate` with `onInvalidCanidate`

This was only needed for working with `@apply`, now this logic _only_
exists in the code path where we are handling `@apply`.

* update `compile` API signature

* update callsite of `compile()` function

* fix typo
2024-03-11 14:24:49 -04:00
Robin Malfait
388d1b0298
add "access": "public" to publishConfig (#13164) 2024-03-08 22:04:05 +01:00
Robin Malfait
d68a4af58e
Prepare next 4.0.0-alpha.7 release (#13163)
* bump versions to `4.0.0-alpha.7`

* update changelog
2024-03-08 21:46:03 +01:00
Kris Braun
065bbd3c99
[v4] Add provenance to all published packages (#13160)
* Add provenance to all packages

Based on #13097 by @saibotk

Add [provenance](https://docs.npmjs.com/generating-provenance-statements) for all published packages.

---
Co-authored-by: saibotk <git@saibotk.de>

* Document reason for id-token permission

* Update changelog
2024-03-08 21:30:13 +01:00
Robin Malfait
c550a62be4
[v4] Make CSS optimization and minification configurable (#13130)
* only run Lightning CSS when passing `--minify` to the CLI

* only optimize the CSS when creating a production build

* add `optimize` option to PostCSS plugin

- The optimize option can be set to `true`, which will optimize
  (unnesting, adding browser prefixes, lowering values) and minify
- The optimize option can also be set to `{ minify: false }`, which will
  optimize but not minify.

* default `optimize` option to the true for `NODE_ENV=production`

* add `--optimize` flag to CLI

This will only optimize the CSS output without minification.

* update `--minify` description

* update changelog
2024-03-08 18:36:07 +01:00
Robin Malfait
d288c52780
bump versions to 4.0.0-alpha.6 2024-03-07 16:00:23 +01:00