Replies: 108 comments 2 replies
-
I looked at this issue and this seems to be happening because of the behaviour implemented in Inside Exploring this further and will raise a PR for this in sometime |
Beta Was this translation helpful? Give feedback.
-
Essentially what I ended up finding was: we should never set I don't know if this was done because of any specific reasons or not but this seems to solve the issue on my local after making these changes. @lfades any thoughts? If it looks good to you then I'll go ahead and raise a PR for this |
Beta Was this translation helpful? Give feedback.
-
Also, to make this work and to have the |
Beta Was this translation helpful? Give feedback.
-
Hi, experiencing the very same issue as reported. |
Beta Was this translation helpful? Give feedback.
-
Experiencing the same issue. I also noticed the I've applied this hack in the mean time: // Add that code to _app.tsx / _app.jsx
import Router from "next/router";
const routeChange = () => {
// Temporary fix to avoid flash of unstyled content
// during route transitions. Keep an eye on this
// issue and remove this code when resolved:
// https://github.com/vercel/next.js/issues/17464
const tempFix = () => {
const allStyleElems = document.querySelectorAll('style[media="x"]');
allStyleElems.forEach((elem) => {
elem.removeAttribute("media");
});
};
tempFix();
};
Router.events.on("routeChangeComplete", routeChange );
Router.events.on("routeChangeStart", routeChange ); I am not sure what other unwished side effects this temporary fix could have, but it seems to work just well enough for my application. |
Beta Was this translation helpful? Give feedback.
-
I'm having the same issue, but @scriptify's fix does not work for me, any ETA for a fix for this? @MihirGH |
Beta Was this translation helpful? Give feedback.
-
@tommhuth It is actually a quick fix but I am not sure if that's how it is supposed to be solved or not. |
Beta Was this translation helpful? Give feedback.
-
@MihirGH That code is just a temporary workaround, it also possible that Next.js is setting the media attribute slightly after those events fire, maybe that's the reason why it's not working for @tommhuth. @tommhuth are you sure that in your case the problem is also related to the |
Beta Was this translation helpful? Give feedback.
-
Having looked into this, I can't see anywhere that media attribute is being changed, but I do see that the relevant Off the top of my head, the only way I could get around this is by moving all style modules into non-module SCSS, but that is quite a significant workaround. |
Beta Was this translation helpful? Give feedback.
-
Hmm that's strange, seems like a severe issue to me, and moving everything into non modular CSS seems like a very tedious task, just to make it modular again when it's fixed (besides the whole disadvantages global CSS has). Are we the only ones using CSS Modules + non-instant route changes? 🤷♂️ Doesn't seem too exotic to me |
Beta Was this translation helpful? Give feedback.
-
@scriptify I was running into this issue as well; your hack worked for me for the time being, so thanks for that. |
Beta Was this translation helpful? Give feedback.
-
@scriptify I bumped into the same issue. could you help me understand where I would add the fix you wrote? Thanks for your help as well |
Beta Was this translation helpful? Give feedback.
-
@fredcorr I put the code in _app.js along with, of course, |
Beta Was this translation helpful? Give feedback.
-
@fredcorr Yea that code is a bit out of context, as @Limekiller mentioned, the best place to put it is |
Beta Was this translation helpful? Give feedback.
-
@Limekiller @scriptify thanks guys that fixed the issue partially, on the first-page transition the issue still occurs. Are you guys using the getStaticProps or GgetServerSideProps? Could that maybe affect it? @MihirGH Any updated on how long will it take to fix this? |
Beta Was this translation helpful? Give feedback.
-
Using this fix https://github.com/moxystudio/next-with-moxy/blob/master/www/app/use-fouc-fix.js from @satazor has fixed any issues for us (calling |
Beta Was this translation helpful? Give feedback.
-
I've got a workaround without using the fix by @satazor! By importing component dynamically (next/dynamic).....the problem of CSS-disabling goes away. // index.js
import dynamic from "next/dynamic";
const Component1 = dynamic(() => import("@path/component1"));
const Component2 = dynamic(() => import("@path/component2"));
export default function Home() {
return (
<>
<Component1/>
<Component2/>
</>
);
} However Page should contain only components & each component has its own CSS Module. This workaround works in my case Next.js 13.1.2 and framer-motion 8.5.2 |
Beta Was this translation helpful? Give feedback.
-
As an alternative, I was looking for a way to completely avoid CSS splitting. It doesn't' make much sense to me, especially for tiny chunks. Changing the optimisation.splitchunks.minsize setting isn't enough, so apparently, there's no way to avoid CSS splitting (even for < 1kb file!). // your_script.js
const path = require('path');
const fs = require('fs');
const CSS_PATH = path.resolve(__dirname, './.next/static/css');
const CSS_FILENAMES = fs.readdirSync(CSS_PATH);
const GLOBAL_CSS_FILENAME = CSS_FILENAMES.find((file) => {
const FILE_PATH = path.join(CSS_PATH, file);
const data = fs.readFileSync(FILE_PATH, 'utf8');
return data.startsWith('html');
});
const GLOBAL_CSS_PATH = path.join(CSS_PATH, GLOBAL_CSS_FILENAME);
CSS_FILENAMES.filter((name) => name !== GLOBAL_CSS_FILENAME).forEach((file) => {
const FILE_PATH = path.join(CSS_PATH, file);
const data = fs.readFileSync(FILE_PATH, 'utf8');
fs.appendFileSync(GLOBAL_CSS_PATH, data);
fs.truncate(FILE_PATH, 0, () => console.log('done'));
}); {
"scripts": {
"build": "next build",
"postbuild": "node your_script.js"
}
} |
Beta Was this translation helpful? Give feedback.
-
Oh, this thread is still alive. I have an update on the hook i posted here almost two years ago: #17464 (comment) The new version below solves a couple of things:
Just call this hook in your [[[ THIS IS BUGGY AND OUTDATED, SEE UPDATE ]]] import * as React from 'react';
export const useNextCssRemovalPrevention = () => {
React.useEffect(() => {
// Remove data-n-p attribute from all link nodes.
// This prevents Next.js from removing server rendered stylesheets.
document.querySelectorAll('head > link[data-n-p]').forEach(linkNode => {
linkNode.removeAttribute('data-n-p');
});
const mutationHandler = (mutations: MutationRecord[]) => {
mutations.forEach(({ target, addedNodes }: MutationRecord) => {
if (target.nodeName === 'HEAD') {
// Add data-n-href-perm attribute to all style nodes with attribute data-n-href,
// and remove data-n-href and media attributes from those nodes.
// This prevents Next.js from removing or disabling dynamic stylesheets.
addedNodes.forEach(node => {
const el = node as Element;
if (el.nodeName === 'STYLE' && el.hasAttribute('data-n-href')) {
const href = el.getAttribute('data-n-href');
if (href) {
el.setAttribute('data-n-href-perm', href);
el.removeAttribute('data-n-href');
el.removeAttribute('media');
}
}
});
// Remove all stylesheets that we don't need anymore
// (all except the two that were most recently added).
const styleNodes = document.querySelectorAll('head > style[data-n-href-perm]');
const requiredHrefs = new Set<string>();
for (let i = styleNodes.length - 1; i >= 0; i--) {
const el = styleNodes[i];
if (requiredHrefs.size < 2) {
const href = el.getAttribute('data-n-href-perm');
if (href) {
if (requiredHrefs.has(href)) {
el.parentNode!.removeChild(el);
} else {
requiredHrefs.add(href);
}
}
} else {
el.parentNode!.removeChild(el);
}
}
}
});
};
// Observe changes to the head element and its descendents.
const observer = new MutationObserver(mutationHandler);
observer.observe(document.head, { childList: true, subtree: true });
return () => {
// Disconnect the observer when the component unmounts.
observer.disconnect();
};
}, []);
}; |
Beta Was this translation helpful? Give feedback.
-
For the Next team (cc @wyattjoh) To help mitigate this issue, maybe you could add a next.config.js flag that, if enabled, lets app developers opt out of the current behavior. A couple ideas how this could behave:
The flag could be called |
Beta Was this translation helpful? Give feedback.
-
this worked for me. Just had to install babel-styled-components, create a babel config and paste in the setup to use the styled components plugin. So far so good! Thanks! |
Beta Was this translation helpful? Give feedback.
-
@DangerousJack I think this works only if you are using babel and not SWC, which is not the case for most people as Next.js is using SWC by default these days |
Beta Was this translation helpful? Give feedback.
-
Same problem here, i hope they will fix that soon (maybe in 1-2 years at this rate :3 ) but thx to @claus his solution works like a charm while waiting for a more official fix ! Thx dude |
Beta Was this translation helpful? Give feedback.
-
with "next": "13.1.6" and "framer-motion": "^10.10.0", this page transition problem is still alive, and through above solutions, can solve the problem in my project. thank you! |
Beta Was this translation helpful? Give feedback.
-
Just a heads up, that updated hook i posted above assumes that one page loads exactly one stylesheet. That's not always the case. In some configurations, pages load more than one stylesheet, breaking my hook. I'll have a fix for that soon. |
Beta Was this translation helpful? Give feedback.
-
Ok, probably my last post on this issue :) We published a PageTransition suite of components, that includes the
Docs Demo |
Beta Was this translation helpful? Give feedback.
-
@claus <3 |
Beta Was this translation helpful? Give feedback.
-
Thank you @claus 🙏🏻 |
Beta Was this translation helpful? Give feedback.
-
Love U |
Beta Was this translation helpful? Give feedback.
-
Looks like this would address this one as well? #68396 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Bug report
Describe the bug
CSS module styling is removed immediately after clicking a
next/link
, instead of after the DOM is removed on production builds. This causes the components to have no styling at all during a page transition. This issue does not happen on dev mode.I believe this is a bug with CSS modules specifically because components styled with
styled-jsx
don't have this problem.Really would love to be able to use Sass via CSS modules here instead of re-writing the entire app I'm working on using
styled-jsx
. If Sass modules can't work in this scenario, I think I would be forced to usestyled-jsx
, which is not my preferred method of styling my components for this project.To Reproduce
I have created repos, and deployed these repos to demonstrate the problem using framer-motion for page transitions. If you were to pull these repos and run them locally using
npm run dev
, you will see that the flash of unstyled content does not happen on any one of them in dev mode. However, on their deployed sites, you can see the flash of unstyled content with CSS modules and Sass modules.styled-jsx
Behavior: correct, no flash of unstyled content
Deployed site on Vercel
Repo
CSS modules
Behavior: buggy, there is a flash of unstyled content immediately after clicking the link
Deployed site on Vercel
Repo
Sass via CSS modules (additional)
Behavior: buggy, there is a flash of unstyled content immediately after clicking the link (same as CSS modules)
Deployed site on Vercel
Repo
Expected behavior
Styling for components that come from CSS modules should not be removed immediately on route changes, and instead, are removed when the markup is removed (the component unmounts?). The expected behavior is the behavior we can see on the
styled-jsx
deployment above.System information
NEXT-1351
Beta Was this translation helpful? Give feedback.
All reactions