0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-20 22:12:38 -05:00

Fix CSS modules ordering (#8877)

This commit is contained in:
Bjorn Lu 2023-10-23 21:22:47 +08:00 committed by GitHub
parent e4ba50162e
commit 26b77b8fef
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 49 additions and 1 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Fixes CSS modules ordering by rendering styles before links

View file

@ -34,7 +34,13 @@ export function renderAllHeadContent(result: SSRResult) {
.filter(uniqueElements)
.map((link) => renderElement('link', link, false));
let content = links.join('\n') + styles.join('\n') + scripts.join('\n');
// Order styles -> links -> scripts similar to src/content/runtime.ts
// The order is usually fine as the ordering between these groups are mutually exclusive,
// except for CSS styles and CSS stylesheet links. However CSS stylesheet links usually
// consist of CSS modules which should naturally take precedence over CSS styles, so the
// order will still work. In prod, all CSS are stylesheet links.
// In the future, it may be better to have only an array of head elements to avoid these assumptions.
let content = styles.join('\n') + links.join('\n') + scripts.join('\n');
if (result._metadata.extraHead.length > 0) {
for (const part of result._metadata.extraHead) {

View file

@ -170,6 +170,15 @@ describe('CSS', function () {
// 2. check CSS
expect(bundledCSS).to.match(new RegExp(`.${moduleClass}[^{]*{font-family:fantasy`));
});
it('.module.css ordering', () => {
const globalStyleClassIndex = bundledCSS.indexOf('.module-ordering');
const moduleStyleClassIndex = bundledCSS.indexOf('._module_ordering');
// css module has higher priority than global style
expect(globalStyleClassIndex).to.be.greaterThan(-1);
expect(moduleStyleClassIndex).to.be.greaterThan(-1);
expect(moduleStyleClassIndex).to.be.greaterThan(globalStyleClassIndex);
});
});
describe('Vue', () => {
@ -412,6 +421,17 @@ describe('CSS', function () {
);
});
it('.module.css ordering', () => {
const globalStyleTag = $('style[data-vite-dev-id$="default.css"]');
const moduleStyleTag = $('link[href$="ModuleOrdering.module.css"]');
const globalStyleClassIndex = globalStyleTag.index();
const moduleStyleClassIndex = moduleStyleTag.index();
// css module has higher priority than global style
expect(globalStyleClassIndex).to.be.greaterThan(-1);
expect(moduleStyleClassIndex).to.be.greaterThan(-1);
expect(moduleStyleClassIndex).to.be.greaterThan(globalStyleClassIndex);
});
it('.css?raw return a string', () => {
const el = $('#css-raw');
expect(el.text()).to.equal('.foo {color: red;}');

View file

@ -0,0 +1,7 @@
import { module_ordering } from './ModuleOrdering.module.css';
export default function Counter() {
return (
<p className={`module-ordering ${module_ordering}`}>This should be green</p>
)
}

View file

@ -0,0 +1,3 @@
.module_ordering {
color: green;
}

View file

@ -1,4 +1,6 @@
---
import '../styles/default.css'
import AstroComponent from '../components/Astro.astro';
import AstroComponentNone from '../components/AstroNone.astro';
import AstroSass from '../components/AstroSass.astro';
@ -19,6 +21,7 @@ import VueScoped from '../components/VueScoped.vue';
import VueScss from '../components/VueScss.vue';
import ReactDynamic from '../components/ReactDynamic.jsx';
import SvelteDynamic from '../components/SvelteDynamic.svelte';
import ModuleOrdering from '../components/ModuleOrdering.jsx';
import '../styles/imported-url.css';
import '../styles/imported.sass';
@ -76,6 +79,7 @@ import raw from '../styles/raw.css?raw'
<ReactDynamic client:load />
<SvelteDynamic client:load />
<pre id="css-raw">{raw}</pre>
<ModuleOrdering />
</div>
</body>
</html>

View file

@ -0,0 +1,3 @@
.module-ordering {
color: red;
}