Repository navigation
Conversation
The styles step ran autoprefixer and cssnano on the main thread; cssnano was about two thirds of its time. Keep postcss-import, postcss-mixins, postcss-simple-vars and postcss-nested, then run Lightning CSS for vendor prefixes and minification, and compile files across worker threads (one per core minus one, up to 8; the main thread for small builds and watch rebuilds). On nymag/sites (2,872 files) `clay vite --only styles` goes from ~17 s to 2.6 s (5.5 s on the main thread), with slightly smaller output. Lightning CSS targets the project's browserslist (or stylesConfig `browserslist`). It treats them as the oldest browsers to support: once all of them support newer syntax it prints that syntax and drops fallbacks. So autoprefixer's overrideBrowserslist (a usage share like '> 2%', which would make it print range media queries Safari < 16.4 ignores) is no longer read; autoprefixerOptions is ignored with a warning. CSS that Lightning CSS cannot parse is an error at its source file and line. Every file still compiles and is written, then the styles step fails so `clay vite` exits non-zero (`--watch` keeps running); files PostCSS cannot compile fail it too. stylesConfig keeps working (it re-runs in each worker) and gains `browserslist` and `lightningcssOptions`; `plugins` still run before Lightning CSS. CLAY-VITE.md documents the options and the CSS patterns Lightning CSS 1.33 mishandles. clay compile is unchanged.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
… package .nvmrc and "engines" say 26.12.1 (the first 26.x with the October 2026 security fixes). CI runs one job that reads .nvmrc instead of a Node 18/20/22 matrix, with the actions pinned by commit. The coveralls npm package was only the old upload script; CI uploads coverage with the Coveralls action. Removing it drops 38 packages from the lockfile (the old `request` chain).
One worker only moves the work to another thread, and with a 2-CPU quota the pool takes CPU from the js step (full sites build in a container: 44.9 s with 8 workers, 40.7 s on the main thread). Node 26 counts a container's CPU quota in os.availableParallelism(), so no cgroup reading is needed.
…rary builds buildDefines() read process.env.NODE_ENV for every pass, but Vite's build() sets it to 'production' when it is unset, and the view and Kiln passes configure in parallel with that. Whichever pass configured after Vite started got 'production' and the other 'development', so which dom-mutator build (and which other library guards) landed in which chunk depended on timing. The value is now read when the config is read, before either pass starts. With Vite 5 both passes happened to read it first; Vite 7 starts sooner, and the Kiln edit bundle came out with a production dom-mutator while the view chunks had the development one.
Vite 5 is unsupported. Vite 7 is ESM-only, which Node 26's require(esm) loads for claycli's CommonJS code, so scripts.js now loads it on first use (Jest's module VM cannot load ESM, and the config helpers need no Vite), and the VITE_CJS_IGNORE_WARNING workaround for Vite 5/6's CJS build is gone. Checked on the nymag/sites build with Node 26 (minified, as shipped): 318 chunks before and after, every chunk with the same set of modules, the same manifest, byte-identical CSS, fonts and generated entries, total size +0.01%, 20.3 s against 20.9 s. 279 chunks are identical once hashed chunk names are normalized; the other 39 differ in how esbuild 0.27 names variables, which also gives most chunks a new hashed URL once. Built unminified (so the minifier is out of the picture), 916 of 947 chunks are identical the same way and 28 of the remaining 31 differ only in how parentheses are printed; the other 3 take Vite 7's own changes: JSON over 10 kB becomes JSON.parse(), and the preload helper gains a Promise.allSettled fallback. --watch rebuilds on edit. The commonjs canary test still passes with Vite 7's bundled @rollup/plugin-commonjs 29.0.x, so claycli's own copy is still needed. Its test patched vite.build, which is a read-only namespace now; it hands scripts.js a wrapped module instead.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The
clay vitestyles step keeps the PostCSS source plugins (postcss-import, postcss-mixins, postcss-simple-vars, postcss-nested, then anystylesConfig.plugins). It then runs Lightning CSS for vendor prefixes and minification, replacing autoprefixer + cssnano, and compiles files across worker threads.On nymag/sites (2,872 styleguide files, Node 24,
CLAYCLI_COMPILE_MINIFIED=true),clay vite --only stylestakes:CLAYCLI_VITE_CSS_WORKERS=0)Output is 0.3% smaller (0.4% gzipped).
Behavior changes
.browserslistrc/package.json, orstylesConfig.browserslist). Lightning CSS treats them as a floor: once every target supports newer syntax it prints that syntax and drops fallbacks. A usage share like> 2%would make nymag/sites print 9,828 range media queries (@media (width>=768px)), which Safari < 16.4 and Chrome < 104 ignore.autoprefixerOptions(includingoverrideBrowserslist) is therefore ignored, with a warning.@import, mixins and nesting), once per location with a count of affected output files. Every file is still compiled and written; then the styles step fails soclay viteexits non-zero (--watchkeeps running). Files PostCSS cannot compile, such as a missing@import, now fail the build too instead of only being logged.stylesConfigkeeps working: it re-runs inside each worker, since plugin instances can't cross threads. It gainsbrowserslistandlightningcssOptions.CLAYCLI_VITE_CSS_WORKERS=<n>overrides the count.clay compile(Browserify) is unchanged.Lightning CSS 1.33 pitfalls
CLAY-VITE.md lists the valid CSS patterns Lightning CSS mishandles and how to write them instead:
fit-contentfollowed by-moz-fit-content;!importantlost when non-adjacent same-selector rules merge;fontprinted after properties it resets;font-stretchprinted as a percentage insidefont;claycli doesn't patch around them; the sites CSS is fixed instead (companion sites PR).
Verification
On nymag/sites, the companion branch's CSS was built with this pipeline and compared against today's production output (rc.10):
Result: 0 unexplained differences, and page heights are equal everywhere. The remaining differences are equivalent spellings (
translate(-50%)fortranslateX(-50%),0vs0%,:is()merges with equal specificity) plus the sites CSS changes listed in that PR.npm testpasses (602 tests).