tailwindcss/packages/@tailwindcss-vite/src/index.ts

582 lines
18 KiB
TypeScript
Raw Normal View History

import { compile, env, Features, Instrumentation, normalizePath } from '@tailwindcss/node'
import { clearRequireCache } from '@tailwindcss/node/require-cache'
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
import { Scanner } from '@tailwindcss/oxide'
import { Features as LightningCssFeatures, transform } from 'lightningcss'
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
import fs from 'node:fs/promises'
import path from 'node:path'
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
import type { Plugin, ResolvedConfig, Rollup, Update, ViteDevServer } from 'vite'
2024-03-05 14:23:26 +01:00
const DEBUG = env.DEBUG
const SPECIAL_QUERY_RE = /[?&](raw|url)\b/
const IGNORED_DEPENDENCIES = ['tailwind-merge']
2024-03-05 14:23:26 +01:00
export default function tailwindcss(): Plugin[] {
let servers: ViteDevServer[] = []
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
let config: ResolvedConfig | null = null
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
let isSSR = false
2024-03-05 14:23:26 +01:00
let minify = false
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
// The Vite extension has two types of sources for candidates:
//
// 1. The module graph: These are all modules that vite transforms and we want
// them to be automatically scanned for candidates.
// 2. Root defined `@source`s
//
// Module graph candidates are global to the Vite extension since we do not
// know which CSS roots will be used for the modules. We are using a custom
// scanner instance with auto source discovery disabled to parse these.
//
// For candidates coming from custom `@source` directives of the CSS roots, we
// create an individual scanner for each root.
//
// Note: To improve performance, we do not remove candidates from this set.
// This means a longer-ongoing dev mode session might contain candidates that
// are no longer referenced in code.
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
let moduleGraphCandidates = new DefaultMap<string, Set<string>>(() => new Set<string>())
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
let moduleGraphScanner = new Scanner({})
let roots: DefaultMap<string, Root> = new DefaultMap((id) => {
let cssResolver = config!.createResolver({
...config!.resolve,
extensions: ['.css'],
mainFields: ['style'],
conditions: ['style', 'development|production'],
tryIndex: false,
preferRelative: true,
})
function customCssResolver(id: string, base: string) {
return cssResolver(id, base, true, isSSR)
}
let jsResolver = config!.createResolver(config!.resolve)
function customJsResolver(id: string, base: string) {
return jsResolver(id, base, true, isSSR)
}
return new Root(
id,
() => moduleGraphCandidates,
config!.base,
customCssResolver,
customJsResolver,
)
})
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
function scanFile(id: string, content: string, extension: string) {
for (let dependency of IGNORED_DEPENDENCIES) {
// We validated that Vite IDs always use posix style path separators, even on Windows.
// In dev build, Vite precompiles dependencies
if (id.includes(`.vite/deps/${dependency}.js`)) {
return
}
// In prod builds, use the node_modules path
if (id.includes(`/node_modules/${dependency}/`)) {
return
}
}
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
let updated = false
for (let candidate of moduleGraphScanner.scanFiles([{ content, extension }])) {
updated = true
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
moduleGraphCandidates.get(id).add(candidate)
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
if (updated) {
invalidateAllRoots()
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
}
function invalidateAllRoots() {
for (let server of servers) {
let updates: Update[] = []
for (let [id] of roots.entries()) {
let module = server.moduleGraph.getModuleById(id)
if (!module) continue
2024-03-05 14:23:26 +01:00
roots.get(id).requiresRebuild = false
server.moduleGraph.invalidateModule(module)
updates.push({
type: `${module.type}-update`,
path: module.url,
acceptedPath: module.url,
timestamp: Date.now(),
})
}
if (updates.length > 0) {
server.hot.send({ type: 'update', updates })
}
2024-03-05 14:23:26 +01:00
}
}
async function regenerateOptimizedCss(
root: Root,
addWatchFile: (file: string) => void,
I: Instrumentation,
) {
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
let content = root.lastContent
let generated = await root.generate(content, addWatchFile, I)
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
if (generated === false) {
return
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
}
DEBUG && I.start('Optimize CSS')
let result = optimizeCss(generated, { minify })
DEBUG && I.end('Optimize CSS')
return result
2024-03-05 14:23:26 +01:00
}
// Manually run the transform functions of non-Tailwind plugins on the given CSS
async function transformWithPlugins(context: Rollup.PluginContext, id: string, css: string) {
let transformPluginContext = {
...context,
getCombinedSourcemap: () => {
throw new Error('getCombinedSourcemap not implemented')
},
}
Apply non-Tailwind CSS transforms in Vite plugin (#14871) Fixes: #14839 Fixes: #14796 This PR fixes an issue in the Vite extension where we previously only ran a small list of allow-listed plugins for the second stage transform in the build step. This caused some CSS features to unexpectedly not work in production builds (one such example is Vue's `:deep(...)` selector). To fix this, I changed the allow listed plugins that we do want to run to a block list to filter out some plugins we know we don't want to run (e.g. the Tailwind Vite plugin for example or some built-in Vite plugins that are not necessary). ## Test plan This PR adds a new integration test suite to test interop with a custom Vite transformer that looks like this: ```js { name: 'recolor', transform(code, id) { if (id.includes('.css')) { return code.replace(/red/g, 'blue') } }, } ``` I also validated that this does indeed fix the Vue `:deep(...)` selector related issue that we were seeing by copying the repro of #14839 into our playground: ![Screenshot 2024-11-05 at 13.35.26.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/0Y77ilPI2WoJfMLFiAEw/4e46ab61-4acf-461a-9e40-f7c9ec3c69b2.png) You can see in the screenshot above that the `:deep()` selector overwrites the scoped styles as expected in both the dev mode and the prod build (screenshotted). Furthermore I reproduced the issue reported in https://github.com/tailwindlabs/tailwindcss/issues/14796 and was able to confirm that in a production build, the styling works as expected: <img width="517" alt="Screenshot 2024-11-06 at 14 26 50" src="https://github.com/user-attachments/assets/ade6fe38-be0d-4bd0-9a9a-67b6fec05ae0"> Lastly, I created a repository out of the biggest known-to-me Vite projects: [Astro, Nuxt, Remix, SolidStart, and SvelteKit](https://github.com/philipp-spiess/tailwind-playgrounds) and verified that both dev and prod builds show no issue and the candidate list is properly appended in each case. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-07 16:26:18 +01:00
for (let plugin of config!.plugins) {
if (!plugin.transform) continue
Apply non-Tailwind CSS transforms in Vite plugin (#14871) Fixes: #14839 Fixes: #14796 This PR fixes an issue in the Vite extension where we previously only ran a small list of allow-listed plugins for the second stage transform in the build step. This caused some CSS features to unexpectedly not work in production builds (one such example is Vue's `:deep(...)` selector). To fix this, I changed the allow listed plugins that we do want to run to a block list to filter out some plugins we know we don't want to run (e.g. the Tailwind Vite plugin for example or some built-in Vite plugins that are not necessary). ## Test plan This PR adds a new integration test suite to test interop with a custom Vite transformer that looks like this: ```js { name: 'recolor', transform(code, id) { if (id.includes('.css')) { return code.replace(/red/g, 'blue') } }, } ``` I also validated that this does indeed fix the Vue `:deep(...)` selector related issue that we were seeing by copying the repro of #14839 into our playground: ![Screenshot 2024-11-05 at 13.35.26.png](https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/0Y77ilPI2WoJfMLFiAEw/4e46ab61-4acf-461a-9e40-f7c9ec3c69b2.png) You can see in the screenshot above that the `:deep()` selector overwrites the scoped styles as expected in both the dev mode and the prod build (screenshotted). Furthermore I reproduced the issue reported in https://github.com/tailwindlabs/tailwindcss/issues/14796 and was able to confirm that in a production build, the styling works as expected: <img width="517" alt="Screenshot 2024-11-06 at 14 26 50" src="https://github.com/user-attachments/assets/ade6fe38-be0d-4bd0-9a9a-67b6fec05ae0"> Lastly, I created a repository out of the biggest known-to-me Vite projects: [Astro, Nuxt, Remix, SolidStart, and SvelteKit](https://github.com/philipp-spiess/tailwind-playgrounds) and verified that both dev and prod builds show no issue and the candidate list is properly appended in each case. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <adam.wathan@gmail.com>
2024-11-07 16:26:18 +01:00
if (plugin.name.startsWith('@tailwindcss/')) {
// We do not run any Tailwind transforms anymore
continue
} else if (
plugin.name.startsWith('vite:') &&
// Apply the vite:css plugin to generated CSS for transformations like
// URL path rewriting and image inlining.
plugin.name !== 'vite:css' &&
// In build mode, since `renderStart` runs after all transformations, we
// need to also apply vite:css-post.
plugin.name !== 'vite:css-post' &&
// The vite:vue plugin handles CSS specific post-processing for Vue
plugin.name !== 'vite:vue'
) {
continue
} else if (plugin.name === 'ssr-styles') {
// The Nuxt ssr-styles plugin emits styles from server-side rendered
// components, we can't run it in the `renderStart` phase so we're
// skipping it.
continue
}
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
let transformHandler =
'handler' in plugin.transform! ? plugin.transform.handler : plugin.transform!
try {
// Directly call the plugin's transform function to process the
// generated CSS. In build mode, this updates the chunks later used to
// generate the bundle. In serve mode, the transformed source should be
// applied in transform.
let result = await transformHandler.call(transformPluginContext, css, id)
if (!result) continue
if (typeof result === 'string') {
css = result
} else if (result.code) {
css = result.code
}
} catch (e) {
console.error(`Error running ${plugin.name} on Tailwind CSS output. Skipping.`)
}
}
return css
}
2024-03-05 14:23:26 +01:00
return [
{
// Step 1: Scan source files for candidates
name: '@tailwindcss/vite:scan',
enforce: 'pre',
configureServer(server) {
servers.push(server)
2024-03-05 14:23:26 +01:00
},
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
async configResolved(_config) {
config = _config
2024-03-05 14:23:26 +01:00
minify = config.build.cssMinify !== false
isSSR = config.build.ssr !== false && config.build.ssr !== undefined
2024-03-05 14:23:26 +01:00
},
// Scan all non-CSS files for candidates
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
transformIndexHtml(html, { path }) {
// SolidStart emits HTML chunks with an undefined path and the html content of `\`.
if (!path) return
scanFile(path, html, 'html')
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
},
transform(src, id, options) {
let extension = getExtension(id)
if (isPotentialCssRootFile(id)) return
scanFile(id, src, extension)
2024-03-05 14:23:26 +01:00
},
},
{
// Step 2 (serve mode): Generate CSS
2024-03-05 14:23:26 +01:00
name: '@tailwindcss/vite:generate:serve',
apply: 'serve',
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
enforce: 'pre',
2024-03-20 16:40:50 -04:00
async transform(src, id, options) {
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
if (!isPotentialCssRootFile(id)) return
2024-03-05 14:23:26 +01:00
using I = new Instrumentation()
I.start('[@tailwindcss/vite] Generate CSS (serve)')
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
let root = roots.get(id)
2024-03-05 14:23:26 +01:00
if (!options?.ssr) {
// Wait until all other files have been processed, so we can extract
// all candidates before generating CSS. This must not be called
// during SSR or it will block the server.
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
//
// The reason why we can not rely on the invalidation here is that the
// users would otherwise see a flicker in the styles as the CSS might
// be loaded with an invalid set of candidates first.
await Promise.all(servers.map((server) => server.waitForRequestsIdle(id)))
}
2024-03-05 14:23:26 +01:00
let generated = await root.generate(src, (file) => this.addWatchFile(file), I)
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
if (!generated) {
roots.delete(id)
return src
}
return { code: generated }
2024-03-05 14:23:26 +01:00
},
},
{
// Step 2 (full build): Generate CSS
name: '@tailwindcss/vite:generate:build',
apply: 'build',
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
enforce: 'pre',
async transform(src, id) {
if (!isPotentialCssRootFile(id)) return
using I = new Instrumentation()
I.start('[@tailwindcss/vite] Generate CSS (build)')
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
let root = roots.get(id)
// We do a first pass to generate valid CSS for the downstream plugins.
// However, since not all candidates are guaranteed to be extracted by
// this time, we have to re-run a transform for the root later.
let generated = await root.generate(src, (file) => this.addWatchFile(file), I)
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
if (!generated) {
roots.delete(id)
return src
}
return { code: generated }
},
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
// `renderStart` runs in the bundle generation stage after all transforms.
// We must run before `enforce: post` so the updated chunks are picked up
// by vite:css-post.
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
async renderStart() {
using I = new Instrumentation()
I.start('[@tailwindcss/vite] (render start)')
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
for (let [id, root] of roots.entries()) {
let generated = await regenerateOptimizedCss(
root,
// During the renderStart phase, we can not add watch files since
// those would not be causing a refresh of the right CSS file. This
// should not be an issue since we did already process the CSS file
// before and the dependencies should not be changed (only the
// candidate list might have)
() => {},
I,
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
)
if (!generated) {
roots.delete(id)
continue
}
// These plugins have side effects which, during build, results in CSS
// being written to the output dir. We need to run them here to ensure
// the CSS is written before the bundle is generated.
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
await transformWithPlugins(this, id, generated)
2024-03-05 14:23:26 +01:00
}
},
},
] satisfies Plugin[]
}
function getExtension(id: string) {
let [filename] = id.split('?', 2)
return path.extname(filename).slice(1)
}
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
function isPotentialCssRootFile(id: string) {
if (id.includes('/.vite/')) return
let extension = getExtension(id)
let isCssFile =
(extension === 'css' || id.includes('&lang.css')) &&
// Don't intercept special static asset resources
!SPECIAL_QUERY_RE.test(id)
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
return isCssFile
}
function optimizeCss(
input: string,
{ file = 'input.css', minify = false }: { file?: string; minify?: boolean } = {},
) {
function optimize(code: Buffer | Uint8Array) {
return transform({
filename: file,
code,
minify,
sourceMap: false,
drafts: {
customMedia: true,
},
nonStandard: {
deepSelectorCombinator: true,
},
include: LightningCssFeatures.Nesting,
exclude:
LightningCssFeatures.LogicalProperties |
LightningCssFeatures.DirSelector |
LightningCssFeatures.LightDark,
targets: {
safari: (16 << 16) | (4 << 8),
ios_saf: (16 << 16) | (4 << 8),
firefox: 128 << 16,
chrome: 111 << 16,
},
errorRecovery: true,
}).code
}
// Running Lightning CSS twice to ensure that adjacent rules are merged after
// nesting is applied. This creates a more optimized output.
return optimize(optimize(Buffer.from(input))).toString()
}
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
function idToPath(id: string) {
return path.resolve(id.replace(/\?.*$/, ''))
}
/**
* A Map that can generate default values for keys that don't exist.
* Generated default values are added to the map to avoid recomputation.
*/
class DefaultMap<K, V> extends Map<K, V> {
constructor(private factory: (key: K, self: DefaultMap<K, V>) => V) {
super()
}
get(key: K): V {
let value = super.get(key)
if (value === undefined) {
value = this.factory(key, this)
this.set(key, value)
}
return value
}
}
class Root {
// Content is only used in serve mode where we need to capture the initial
// contents of the root file so that we can restore it during the
// `renderStart` hook.
public lastContent: string = ''
// The lazily-initialized Tailwind compiler components. These are persisted
// throughout rebuilds but will be re-initialized if the rebuild strategy is
// set to `full`.
private compiler?: Awaited<ReturnType<typeof compile>>
public requiresRebuild: boolean = true
// This is the compiler-specific scanner instance that is used only to scan
// files for custom @source paths. All other modules we scan for candidates
// will use the shared moduleGraphScanner instance.
private scanner?: Scanner
// List of all candidates that were being returned by the root scanner during
// the lifetime of the root.
private candidates: Set<string> = new Set<string>()
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
// List of all dependencies captured while generating the root. These are
// retained so we can clear the require cache when we rebuild the root.
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
private dependencies = new Set<string>()
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
// The resolved path given to `source(…)`. When not given this is `null`.
private basePath: string | null = null
Vite: Don't track candidate changes for Svelte `<style>` tags (#14981) Closes #14965 This PR changes the way we register Tailwind CSS as a Svelte preprocessor when using the Vite plugin. The idea is to reduce the bookkeeping for interacting with CSS inside `<style>` tags so that we have a more consistent behavior and make sure the Svelte-specific post-processing (e.g. local class mangling) works as expected. Prior to this change, we were running Tailwind CSS as a Svelte preprocessor and then we would transform the file again when necessary inside the Vite `transform` hook. This is necessary to have the right list of candidates when we build the final CSS, but it did cause some situation to not apply the Svelte post-processors anymore. The repro for this seemed to indicate a timing specific issue and I did notice that specifically the code where we invalidate modules in Vite would cause unexpected processing orders. We do, however, not officially support rendering utilities (`@tailwind utilities;`) inside `<style>` tag. This is because the `<style>` block is scoped by default and emitting utilities will always include utilities for all classes in your whole project. For this case, we highly recommend creating as separate `.css` file and importing it explicitly. With this limitation in place, the additional bookkeeping where we need to invalidate modules because the candidate list has changed is no longer necessary and removing it allows us to reduce the complexity of the Svelte integration. ## Test Plan https://github.com/user-attachments/assets/32c8e91f-ab21-48c6-aeaf-2582273b9bac Not seen in the test plan above I also tested the `pnpm build --watch` step of the Vite project. This does require the `pnpm preview` server to restart but the build artifact are updated as expected.
2024-11-13 16:42:49 +01:00
public overwriteCandidates: string[] | null = null
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
constructor(
private id: string,
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
private getSharedCandidates: () => Map<string, Set<string>>,
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
private base: string,
private customCssResolver: (id: string, base: string) => Promise<string | false | undefined>,
private customJsResolver: (id: string, base: string) => Promise<string | false | undefined>,
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
) {}
// Generate the CSS for the root file. This can return false if the file is
// not considered a Tailwind root. When this happened, the root can be GCed.
public async generate(
content: string,
addWatchFile: (file: string) => void,
I: Instrumentation,
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
): Promise<string | false> {
this.lastContent = content
let inputPath = idToPath(this.id)
let inputBase = path.dirname(path.resolve(inputPath))
if (!this.compiler || !this.scanner || this.requiresRebuild) {
clearRequireCache(Array.from(this.dependencies))
this.dependencies = new Set([idToPath(inputPath)])
DEBUG && I.start('Setup compiler')
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
this.compiler = await compile(content, {
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
base: inputBase,
shouldRewriteUrls: true,
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
onDependency: (path) => {
addWatchFile(path)
this.dependencies.add(path)
},
customCssResolver: this.customCssResolver,
customJsResolver: this.customJsResolver,
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
})
DEBUG && I.end('Setup compiler')
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
let sources = (() => {
// Disable auto source detection
if (this.compiler.root === 'none') {
return []
}
// No root specified, use the module graph
if (this.compiler.root === null) {
return []
}
// Use the specified root
return [this.compiler.root]
})().concat(this.compiler.globs)
this.scanner = new Scanner({ sources })
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
if (
!(
this.compiler.features &
(Features.AtApply | Features.JsPluginCompat | Features.ThemeFunction | Features.Utilities)
)
) {
return false
}
if (!this.overwriteCandidates || this.compiler.features & Features.Utilities) {
Vite: Don't track candidate changes for Svelte `<style>` tags (#14981) Closes #14965 This PR changes the way we register Tailwind CSS as a Svelte preprocessor when using the Vite plugin. The idea is to reduce the bookkeeping for interacting with CSS inside `<style>` tags so that we have a more consistent behavior and make sure the Svelte-specific post-processing (e.g. local class mangling) works as expected. Prior to this change, we were running Tailwind CSS as a Svelte preprocessor and then we would transform the file again when necessary inside the Vite `transform` hook. This is necessary to have the right list of candidates when we build the final CSS, but it did cause some situation to not apply the Svelte post-processors anymore. The repro for this seemed to indicate a timing specific issue and I did notice that specifically the code where we invalidate modules in Vite would cause unexpected processing orders. We do, however, not officially support rendering utilities (`@tailwind utilities;`) inside `<style>` tag. This is because the `<style>` block is scoped by default and emitting utilities will always include utilities for all classes in your whole project. For this case, we highly recommend creating as separate `.css` file and importing it explicitly. With this limitation in place, the additional bookkeeping where we need to invalidate modules because the candidate list has changed is no longer necessary and removing it allows us to reduce the complexity of the Svelte integration. ## Test Plan https://github.com/user-attachments/assets/32c8e91f-ab21-48c6-aeaf-2582273b9bac Not seen in the test plan above I also tested the `pnpm build --watch` step of the Vite project. This does require the `pnpm preview` server to restart but the build artifact are updated as expected.
2024-11-13 16:42:49 +01:00
// This should not be here, but right now the Vite plugin is setup where we
// setup a new scanner and compiler every time we request the CSS file
// (regardless whether it actually changed or not).
DEBUG && I.start('Scan for candidates')
Vite: Don't track candidate changes for Svelte `<style>` tags (#14981) Closes #14965 This PR changes the way we register Tailwind CSS as a Svelte preprocessor when using the Vite plugin. The idea is to reduce the bookkeeping for interacting with CSS inside `<style>` tags so that we have a more consistent behavior and make sure the Svelte-specific post-processing (e.g. local class mangling) works as expected. Prior to this change, we were running Tailwind CSS as a Svelte preprocessor and then we would transform the file again when necessary inside the Vite `transform` hook. This is necessary to have the right list of candidates when we build the final CSS, but it did cause some situation to not apply the Svelte post-processors anymore. The repro for this seemed to indicate a timing specific issue and I did notice that specifically the code where we invalidate modules in Vite would cause unexpected processing orders. We do, however, not officially support rendering utilities (`@tailwind utilities;`) inside `<style>` tag. This is because the `<style>` block is scoped by default and emitting utilities will always include utilities for all classes in your whole project. For this case, we highly recommend creating as separate `.css` file and importing it explicitly. With this limitation in place, the additional bookkeeping where we need to invalidate modules because the candidate list has changed is no longer necessary and removing it allows us to reduce the complexity of the Svelte integration. ## Test Plan https://github.com/user-attachments/assets/32c8e91f-ab21-48c6-aeaf-2582273b9bac Not seen in the test plan above I also tested the `pnpm build --watch` step of the Vite project. This does require the `pnpm preview` server to restart but the build artifact are updated as expected.
2024-11-13 16:42:49 +01:00
for (let candidate of this.scanner.scan()) {
this.candidates.add(candidate)
}
DEBUG && I.end('Scan for candidates')
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
if (this.compiler.features & Features.Utilities) {
// Watch individual files found via custom `@source` paths
for (let file of this.scanner.files) {
addWatchFile(file)
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
// Watch globs found via custom `@source` paths
for (let glob of this.scanner.globs) {
if (glob.pattern[0] === '!') continue
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
let relative = path.relative(this.base, glob.base)
if (relative[0] !== '.') {
relative = './' + relative
}
// Ensure relative is a posix style path since we will merge it with the
// glob.
relative = normalizePath(relative)
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
addWatchFile(path.posix.join(relative, glob.pattern))
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
let root = this.compiler.root
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
if (root !== 'none' && root !== null) {
let basePath = normalizePath(path.resolve(root.base, root.pattern))
let isDir = await fs.stat(basePath).then(
(stats) => stats.isDirectory(),
() => false,
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
)
if (!isDir) {
throw new Error(
`The path given to \`source(…)\` must be a directory but got \`source(${basePath})\` instead.`,
)
}
this.basePath = basePath
} else if (root === null) {
this.basePath = null
}
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
}
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
this.requiresRebuild = true
DEBUG && I.start('Build CSS')
Vite: Don't track candidate changes for Svelte `<style>` tags (#14981) Closes #14965 This PR changes the way we register Tailwind CSS as a Svelte preprocessor when using the Vite plugin. The idea is to reduce the bookkeeping for interacting with CSS inside `<style>` tags so that we have a more consistent behavior and make sure the Svelte-specific post-processing (e.g. local class mangling) works as expected. Prior to this change, we were running Tailwind CSS as a Svelte preprocessor and then we would transform the file again when necessary inside the Vite `transform` hook. This is necessary to have the right list of candidates when we build the final CSS, but it did cause some situation to not apply the Svelte post-processors anymore. The repro for this seemed to indicate a timing specific issue and I did notice that specifically the code where we invalidate modules in Vite would cause unexpected processing orders. We do, however, not officially support rendering utilities (`@tailwind utilities;`) inside `<style>` tag. This is because the `<style>` block is scoped by default and emitting utilities will always include utilities for all classes in your whole project. For this case, we highly recommend creating as separate `.css` file and importing it explicitly. With this limitation in place, the additional bookkeeping where we need to invalidate modules because the candidate list has changed is no longer necessary and removing it allows us to reduce the complexity of the Svelte integration. ## Test Plan https://github.com/user-attachments/assets/32c8e91f-ab21-48c6-aeaf-2582273b9bac Not seen in the test plan above I also tested the `pnpm build --watch` step of the Vite project. This does require the `pnpm preview` server to restart but the build artifact are updated as expected.
2024-11-13 16:42:49 +01:00
let result = this.compiler.build(
this.overwriteCandidates
? this.overwriteCandidates
: [...this.sharedCandidates(), ...this.candidates],
)
DEBUG && I.end('Build CSS')
return result
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
private sharedCandidates(): Set<string> {
if (!this.compiler) return new Set()
if (this.compiler.root === 'none') return new Set()
const HAS_DRIVE_LETTER = /^[A-Z]:/
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
let shouldIncludeCandidatesFrom = (id: string) => {
if (this.basePath === null) return true
if (id.startsWith(this.basePath)) return true
// This is a windows absolute path that doesn't match so return false
if (HAS_DRIVE_LETTER.test(id)) return false
// We've got a path that's not absolute and not on Windows
// TODO: this is probably a virtual module -- not sure if we need to scan it
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
if (!id.startsWith('/')) return true
// This is an absolute path on POSIX and it does not match
return false
Auto source detection improvements (#14820) This PR introduces a new `source(…)` argument and improves on the existing `@source`. The goal of this PR is to make the automatic source detection configurable, let's dig in. By default, we will perform automatic source detection starting at the current working directory. Auto source detection will find plain text files (no binaries, images, ...) and will ignore git-ignored files. If you want to start from a different directory, you can use the new `source(…)` next to the `@import "tailwindcss/utilities" layer(utilities) source(…)`. E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss/utilities' layer(utilities) source('../../'); ``` Most people won't split their source files, and will just use the simple `@import "tailwindcss";`, because of this reason, you can use `source(…)` on the import as well: E.g.: ```css /* ./src/styles/index.css */ @import 'tailwindcss' source('../../'); ``` Sometimes, you want to rely on auto source detection, but also want to look in another directory for source files. In this case, yuo can use the `@source` directive: ```css /* ./src/index.css */ @import 'tailwindcss'; /* Look for `blade.php` files in `../resources/views` */ @source '../resources/views/**/*.blade.php'; ``` However, you don't need to specify the extension, instead you can just point the directory and all the same automatic source detection rules will apply. ```css /* ./src/index.css */ @import 'tailwindcss'; @source '../resources/views'; ``` If, for whatever reason, you want to disable the default source detection feature entirely, and only want to rely on very specific glob patterns you define, then you can disable it via `source(none)`. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Only look at .blade.php files, nothing else */ @source "../resources/views/**/*.blade.php"; ``` Note: even with `source(none)`, if your `@source` points to a directory, then auto source detection will still be performed in that directory. If you don't want that, then you can simply add explicit files in the globs as seen in the previous example. ```css /* Completely disable the default auto source detection */ @import 'tailwindcss' source(none); /* Run auto source detection in `../resources/views` */ @source "../resources/views"; ``` --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-10-29 21:33:34 +01:00
}
let shared = new Set<string>()
for (let [id, candidates] of this.getSharedCandidates()) {
if (!shouldIncludeCandidatesFrom(id)) continue
for (let candidate of candidates) {
shared.add(candidate)
}
}
return shared
}
Rework Vite plugin to support lightningcss pre processor and fast rebuilds (#14269) Fixes #14205 Fixes #14106 This PR reworks the Vite extension in order to supprt `lightningcss` as the pre-processor, enable faster rebuilds, and adds support for `vite build --watch` mode. To make this change possible, we've done two major changes to the extension that have caused the other changes. ## 1. Tailwind CSS is a preprocessor We now run all of our modifications in `enforce: 'pre'`. This means that Tailwind CSS now gets the untransformed CSS files rather than the one already going through postcss or lightningcss. We do this because Tailwind CSS _is_ a preprocessor at the same level as those tools and we do sometimes use the language in ways that [creates problems when it's the input for other bundlers](https://github.com/tailwindlabs/tailwindcss/pull/14269). The correct solution here is to make Tailwind not depend on any other transformations. The main reason we were not using the `enforce: 'pre'` phase in Vite before was becuase we relied on the `@import` flattening of postcss so we now have to do this manually. `@import` flattening is now a concern that every Tailwind V4 client has to deal with so this might actually be something we want to inline into tailwindcss in the future. ## 2. A Vite config can have multiple Tailwind roots This is something that we have not made very explicit in the previous iteration of the Vite plugin but we have to support multiple Tailwind roots in a single Vite workspace. A Tailwind root is a CSS file that is used to configure Tailwind. Technically, any CSS file can be the input for `tailwindcss` but you have to add certain rules (e.g. `@import "tailwindcss";`) to make the compiler do something. A workspace can have multiple of these rules (e.g. by having different Tailwind configures for different sub-pages). With the addition of [support for `@source` rules](https://github.com/tailwindlabs/tailwindcss/pull/14078) and [JS config files](https://github.com/tailwindlabs/tailwindcss/pull/14239), Tailwind roots become more complex and can have a custom list of _dependencies_ (that is other JavaScript modules the compiler includes as part of these new rules). In order to _only rebuild the roots we need to_, we have to make this separation very clear. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me> Co-authored-by: Adam Wathan <4323180+adamwathan@users.noreply.github.com>
2024-09-04 10:09:24 +02:00
}