Closed markgomez closed 6 months ago
Looks like with build.inlineStylesheet: 'none'
, the CSS will exist in dist/client
, however the node server will still not serve the CSS file, seems like something is off here.
This must have been a tricky one to pinpoint, thanks!
Makes sense why the CSS file gets deleted, nothing is referring to it. Must be a module graph bug. An adapter is not necessary for the bug to appear.
I'm getting a similar situation with an upgrade to Astro 3, however it seems to happen to all of my custom markdoc tags and custom heading ie, on dev server, styles get applied, but on build, the styles are missing. Other page styles seem ok. Worked on Astro 2.x too.
Astro v3.6.3
Node v18.16.0
System MacOS
Package Manager yarn
Output 'static'
Adapter None
Integrations @astrojs/react, @astrojs/markdoc, @astrojs/sitemap
I've also tried the following, which doesn't change anything:
build.inlineStylesheet: 'never'
and build.inlineStylesheet: 'always'
I'm trying to untangle my current project and create a stackblitz reproduction of this...
@lilnasy
Must be a module graph bug
Do you know where the module graph code is? I'm trying to debug the internals of astro, but not sure where to look. I have a working example using Astro 2.8.0, and a broken example using Astro 3.6.4, and I'm trying to see what the difference is.
(It does work on a clean build using Astro 3, so it could very well be something in our code or some edge case combination of integrations)
You can ignore my comments above, mine was another issue: https://github.com/withastro/astro/issues/9347#issuecomment-1849950846
After playing around with this some more, it appears at least one .astro
page needs to reference a stylesheet (can be any) in order for custom styles to be injected into <head>
. Without that minimum reference (even when build.inlineStylesheet
set to never
bundles a .css
file), custom styles will not be applied in the production build because <head>
won't contain any references to them (only the astro-*
CSS classes will be there).
As a workaround, I ended up using a wrapper <div>
to create the minimum reference needed to trigger inclusion of all subsequent styles:
<div className={Styles.app}>
<React.StrictMode>
<App client:only="react" />
</React.StrictMode>
</div>
Interestingly, the <style>
tag containing the astro-*
CSS classes are moved out of <head>
and into the wrapper <div>
while custom styles were injected into <head>
.
Here's the full working example: https://stackblitz.com/edit/astro-node-ssr-react-styles-issue-workaround
I guess this is minor with Mark's workaround but breaking CSS modules in prod seems pretty important to me!
The reproduction is fixed if you provide the full HTML structure:
---
export const prerender = false;
import Router from "../components/Router";
---
<html>
<head>
</head>
<body>
<Router client:only="react" />
</body>
</html>
Is everyone else's issue caused by not having the html and head tag?
I believe I'm seeing the same issue. I'm using Keystatic and it allows you to create your own react components for custom MDX component previews. So also a react component where styles work in dev, but not in prod. I'm using hybrid rendering with @astrojs/netlify integration.
It's a simple component, but here's what it looks like:
// style import
import "@/styles/keystatic.css";
interface Props {
variant: "tip" | "caution" | "danger" | "info";
}
const KeystaticAdmonition = ({
variant,
children,
}: Props & { children: React.ReactNode }) => {
let color;
if (variant === "tip") {
color = "#6ee7b7";
} else if (variant === "caution") {
color = "#fcd34d";
} else if (variant === "danger") {
color = "#fca5a5";
} else {
color = "#7dd3fc";
}
return (
<div className="ks-admonition" style={{ borderColor: color }}>
<h5 className="ks-admonition__variant">{variant}</h5>
<div>{children}</div>
</div>
);
};
export default KeystaticAdmonition;
And then here's the css file
.ks-admonition {
border-radius: 0.375rem /* 6px */;
border-left: 4px solid;
padding-left: 1rem /* 16px */;
padding-right: 1rem /* 16px */;
padding-top: 0.75rem /* 12px */;
padding-bottom: 0.75rem /* 12px */;
}
.ks-admonition__variant {
font-weight: 700;
text-transform: uppercase;
}
Since there's no response to my question I'm going to assume this isn't a pressing issue. It is fixed by providing the full HTML structure. If anyone runs into a similar bug please feel free to file a new issue.
Hey @Boston343 did you solve this? I'm seeing the same with a setup like below. All's well when developing locally but the production build isn't including inline styles or referencing a stylesheet. I have "full HTML structure" but it's in the layout, not the page.
MDX content e.g. src/content/articles/my-article.mdx
---
layout: "../../layouts/article-layout-bulma.astro"
title: "My title"
---
My content.
Astro layout e.g. src/layouts/article-layout-bulma.astro
---
import "../styles/bulma.scss";
const { frontmatter } = Astro.props;
---
<html lang="en-GB">
<head>
<meta charset="utf-8" />
<title>{frontmatter.title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body class="bulma-columns bulma-container bulma-is-max-desktop">
<article class="bulma-column bulma-content">
<div class="">
<h1>{frontmatter.title}</h1>
<slot />
</div>
</article>
</body>
</html>
Astro page e.g. src/pages/articles/[...slug].astro
---
import { getCollection } from "astro:content";
// 1. Generate a new path for every collection entry
export async function getStaticPaths() {
const blogEntries = await getCollection("articles");
return blogEntries.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}
// 2. For your template, you can get the entry directly from the prop
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<Content />
SCSS Style e.g. src/styles/bulma.scss
@use "../node_modules/bulma/sass/utilities/initial-variables" with (
$class-prefix: "bulma-"
);
@use "../node_modules/bulma/sass/themes";
@use "../node_modules/bulma/sass/base";
@use "../node_modules/bulma/sass/elements/content";
@use "../node_modules/bulma/sass/grid/columns";
@use "../node_modules/bulma/sass/layout";
For anyone coming to this, I removed the root cause of the error in my simplified examples above.
The root cause was I had a <style>
tag in my Layout file. Astro doesn't seem to like that and generated output that was missing both a <html>
tag and a <head>
tag … so there wasn't a full HTML structure.
Just throwing it out there, when following the CRA => Astro Docs it suggests:
---
// Import your root App component
import App from '../cra-project/App.jsx';
---
<!-- Use a client directive to load your app -->
<App client:load />
Which resulted in the weird behavior where CSS imported by the react-component worked in dev but got dropped in prod.
Might be worth mentioning you may need something like <html><head></head><body><App client:load></body></html>
to actually get the desired result.
This was somewhat tricky to debug and find the answer here. If it's easy to do, I'd suggest adding a warning if an astro page lacks the valid HTML that allows CSS to be added in prod?
Astro Info
If this issue only occurs in one browser, which browser is a problem?
All browsers
Describe the Bug
CSS styles (Sass) in React project (Node SSR) appears in
dev
only, i.e., the production build is unstyled.When inspecting page elements via Chrome's developer tools after running
astro dev
:But after running
astro build && node ./dist/server/entry.mjs
:To reproduce the issue:
npm install && npm run dev
to complete.dev
server (Ctrl + C).npm run build && npm start
What's the expected result?
Production build should be styled.
Link to Minimal Reproducible Example
https://stackblitz.com/edit/astro-node-ssr-react-styles-issue
Participation