summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/silent-goats-invent.md5
-rw-r--r--packages/astro/src/runtime/server/render/head.ts8
-rw-r--r--packages/astro/test/0-css.test.js20
-rw-r--r--packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.jsx7
-rw-r--r--packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.module.css3
-rw-r--r--packages/astro/test/fixtures/0-css/src/pages/index.astro4
-rw-r--r--packages/astro/test/fixtures/0-css/src/styles/default.css3
7 files changed, 49 insertions, 1 deletions
diff --git a/.changeset/silent-goats-invent.md b/.changeset/silent-goats-invent.md
new file mode 100644
index 000000000..1ebb37772
--- /dev/null
+++ b/.changeset/silent-goats-invent.md
@@ -0,0 +1,5 @@
+---
+'astro': patch
+---
+
+Fixes CSS modules ordering by rendering styles before links
diff --git a/packages/astro/src/runtime/server/render/head.ts b/packages/astro/src/runtime/server/render/head.ts
index bad8140ec..20e3c7143 100644
--- a/packages/astro/src/runtime/server/render/head.ts
+++ b/packages/astro/src/runtime/server/render/head.ts
@@ -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) {
diff --git a/packages/astro/test/0-css.test.js b/packages/astro/test/0-css.test.js
index 9371673d4..2120452eb 100644
--- a/packages/astro/test/0-css.test.js
+++ b/packages/astro/test/0-css.test.js
@@ -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;}');
diff --git a/packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.jsx b/packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.jsx
new file mode 100644
index 000000000..2983d2bb2
--- /dev/null
+++ b/packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.jsx
@@ -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>
+ )
+}
diff --git a/packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.module.css b/packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.module.css
new file mode 100644
index 000000000..dfd292ea2
--- /dev/null
+++ b/packages/astro/test/fixtures/0-css/src/components/ModuleOrdering.module.css
@@ -0,0 +1,3 @@
+.module_ordering {
+ color: green;
+}
diff --git a/packages/astro/test/fixtures/0-css/src/pages/index.astro b/packages/astro/test/fixtures/0-css/src/pages/index.astro
index e0f693feb..c11fe1166 100644
--- a/packages/astro/test/fixtures/0-css/src/pages/index.astro
+++ b/packages/astro/test/fixtures/0-css/src/pages/index.astro
@@ -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>
diff --git a/packages/astro/test/fixtures/0-css/src/styles/default.css b/packages/astro/test/fixtures/0-css/src/styles/default.css
new file mode 100644
index 000000000..222079a59
--- /dev/null
+++ b/packages/astro/test/fixtures/0-css/src/styles/default.css
@@ -0,0 +1,3 @@
+.module-ordering {
+ color: red;
+}