feat(sui-bundler): add plainCssPackages config to bypass sass-loader#1988
Merged
Conversation
…s-loader Adds a new `plainCssPackages` option to `sui-bundler` config that allows projects to specify npm packages whose CSS files should skip the sass-loader pipeline entirely. Packages that ship pre-compiled CSS (e.g. Tailwind CSS v4 output) use modern CSS syntax (@layer, @Property, nested rules) that Dart Sass cannot parse. This causes `Error: expected ";"` at build time. Usage in package.json: ```json { "config": { "sui-bundler": { "plainCssPackages": ["@adv-mt/ui", "@adv-mt/theme"] } } } ``` CSS files from listed packages are processed only by css-loader (+ MiniCssExtractPlugin or style-loader), bypassing postcss-loader and sass-loader. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
kikoruiz
approved these changes
May 26, 2026
ferransimon
approved these changes
Jun 18, 2026
…to AppStyles chunk Prevents webpack from splitting CSS of configured packages into separate async chunks, ensuring SSR injects them on first render (no FOUC). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…les chunk Replace splitChunks cacheGroups approach with a webpack plugin that moves css/mini-extract modules from configured packages into the AppStyles chunk at afterOptimizeChunks. More reliable regardless of chunk size thresholds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…les config Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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.
Summary
Adds two new config options to
sui-bundler:plainCssPackages— allows consumer apps to specify npm packages whose.cssfiles should be loaded with onlycss-loader, completely bypassing@s-ui/sass-loaderandpostcss-loader.cssInAppStyles— forces CSS modules from specified packages into theAppStyleschunk, preventing webpack'ssplitChunksfrom extracting them into separate async chunks that@s-ui/ssrdoesn't inject — avoiding Flash of Unstyled Content (FOUC).Problem
Sass parse errors on modern CSS
sui-bundlerroutes all.cssand.scssfiles through the full Sass + PostCSS pipeline — including third-party packages that ship pre-compiled Tailwind CSS v4 output. Dart Sass interprets valid CSS constructs (liketransition-property: transform, ...) as Sass spread syntax, causing fatal build errors:```
Error: expected ";"
╷
│ transition-property:transform,...;
│ ^^^
╵
```
This blocks any consumer app from importing packages that emit modern CSS not compatible with the Sass parser (e.g.
@adv-mt/uiwhich uses Tailwind CSS v4).Flash of Unstyled Content
When importing CSS from packages like
@adv-mt/ui/styles.cssvia JS, webpack'ssplitChunksextracts it into a separate async chunk (e.g.7100.css) because it exceeds the 30KB threshold.@s-ui/ssronly injects the configuredAppStyleschunk, so DS styles arrive ~1.5s after first paint — components render without styles and visually "jump".Solution
Two new config keys under
config.sui-bundlerin the consumer'spackage.json:{ "config": { "sui-bundler": { "plainCssPackages": ["@adv-mt/ui", "@adv-mt/theme"], "cssInAppStyles": ["@adv-mt/ui", "@adv-mt/theme"] } } }plainCssPackagesWhen set, the bundler:
node_modules/<package>/.cssfiles from those packages, using justcss-loader(+MiniCssExtractPlugin.loaderorstyle-loaderdepending on the webpack config)cssInAppStylesWhen set, the bundler adds a webpack plugin that:
afterOptimizeChunksin the compilationcss/mini-extractmodules from the configured packagesAppStyleschunk, so@s-ui/ssrinjects them in the initial HTMLFiles changed
shared/module-rules-sass.jsshared/plain-css-split-chunks.jswebpack.config.client.dev.jssassRules(was duplicating inline rules)webpack.config.dev.jsplainCssPackagessupport withstyle-loader(SPA dev mode)webpack.config.prod.jssassRulesas array + integratescssInAppStylespluginwebpack.config.lib.jssassRulesas arraytest/server/plainCssSplitChunksSpec.jscssInAppStylespluginREADME.mdUsage
{ "config": { "sui-bundler": { "plainCssPackages": ["@adv-mt/ui", "@adv-mt/theme"], "cssInAppStyles": ["@adv-mt/ui", "@adv-mt/theme"] } } }Then
import '@adv-mt/ui/styles.css'works without Sass errors, and the styles are bundled intoAppStyles.css— no FOUC.Test plan
@adv-mt/ui@2.3.0CSS builds without Sass errorsfrontend-ma--web-app#7667): build passes, styles inAppStyleschunk, no FOUCplainCssSplitChunksSpec.js)🤖 Generated with Claude Code