Comments (2)
This problem exists when there is an app with enabled CSS extraction and another app that uses runtime insertion on the same page (example: https://stackblitz.com/edit/stackblitz-starters-6gpxe7), i.e. multi bundle scenario.
Basically:
- App1 (runtime insertion) + App2 (runtime insertion) = 😐 (both bundles will insert rules, but rules will not collide)
- App1 (runtime insertion) + App2 (CSS extraction) = 💣 (blows up due order of CSS)
Workaround time
This is tricky, there are two ways:
Change classes prefixNot an option as Fluent compiles styles, classes can't be changed in runtime- Increase specificity on a renderer that does runtime insertion
The second option is more realistic as we just need to modify CSS rules. This can be done with createEnhancedRenderer()
available below.
createEnhancedRenderer()
import { createDOMRenderer } from '@griffel/core';
import type { CreateDOMRendererOptions, GriffelRenderer } from '@griffel/core';
import { serialize, compile, stringify } from 'stylis';
const ENHANCE_CACHE: Record<string, string> = {};
export function enhanceCSSRule(className: string, cssRule: string) {
if (!ENHANCE_CACHE[className + cssRule]) {
ENHANCE_CACHE[className + cssRule] = serialize(compile(`.${className} {${cssRule} }`), stringify);
}
return ENHANCE_CACHE[className + cssRule];
}
export const createEnhancedRenderer = (
document: Document | undefined,
options: CreateDOMRendererOptions & { specificityClassName: string },
): GriffelRenderer => {
const { specificityClassName } = options;
const originalRenderer = createDOMRenderer(document, options);
return {
...originalRenderer,
insertCSSRules(cssRules) {
const rules = Object.fromEntries(
Object.entries(cssRules).map(([bucketName, cssRulesInBucket]) => {
return [
bucketName,
cssRulesInBucket.map(cssEntry => {
if (typeof cssEntry === 'string') {
return enhanceCSSRule(specificityClassName, cssEntry);
}
return [enhanceCSSRule(specificityClassName, cssEntry[0]), cssEntry[1]];
}),
];
}),
);
originalRenderer.insertCSSRules(rules);
},
};
};
Then it could be used like that:
const renderer = createEnhancedRenderer(document, {
specificityClassName: 'foo',
// ❗ This is mandatory, runtime styles should be inserted before CSS stylesheet
insertionPoint: document.head.firstChild,
});
<RendererProvider renderer={renderer}>
<div className="foo">{/* children */}</div>
</RendererProvider>
All together: https://stackblitz.com/edit/vitejs-vite-d11ccd
Proper solution
We should stop compiling styles on library styles i.e. Fluent should ship not optimized styles, so we can process them in runtime/build time. This requires wider discussion as then by default, Fluent will become slower and will require AOT processing.
After that, we can implement the option mentioned in this feature request & consider API for processors/plugins.
from griffel.
With the addition of shorthand support in #531 - This problem grows since we can no longer assume that one CSS class overrides one property at a time
<style>
/* extracted-bundle-1.css */
.shorthand {
margin: 1px;
}
.longhand {
margin-left: 2px
}
/* extracted-bundle-2.css */
.shorthand {
margin: 1px
}
</style>
<!-- from bundle-1.js
<!-- ⚠️ you would expect "margin-left: 2px" to be applied but it's not -->
<div class="longhand shorthand"></div>
from griffel.
Related Issues (20)
- core: shorthands.gridArea() does not expand custom idents properly HOT 7
- core: Support object literal with multiline keys HOT 2
- Can we cache the `makeStyles` internal HOT 2
- Failed to override styles when selectors are grouped
- lint: add lint rule which warn unused makeStyles classes HOT 2
- vite: add support for CSS extraction HOT 2
- core: add support for fallback properties in `makeStaticStyles` HOT 3
- lint: forbid comma separated selectors in selectors HOT 2
- `shorthands.flex(1)` should produce `flex: 1 1 0%` instead of `flex: 1 1 0px` HOT 3
- Vite plugin: TypeError: griffel is not a function HOT 5
- eslint-plugin: Is not compatible with eslint 8.x HOT 2
- eslint-plugin: add no-unnecesary-shorthands rule HOT 1
- `csstype` bump to 3.1.3 causing BREAKING CHANGEs on type-level
- babel-preset: transforms don't work with native ESM packages that use `.mjs` HOT 2
- babel-preset: transforms dont work with `swc` commonjs output HOT 1
- makeResetStyles should not override makeStyles HOT 2
- core: add support for CSS shorthands HOT 6
- docs: add mergeClasses() to playground
- babel-preset: huge perf slowdown on first babel transform invoction
- core: `makeStaticStyles` to support @at-rules HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from griffel.