Next.js: CSS is reset on route change in production build

Created on 27 Oct 2020  路  9Comments  路  Source: vercel/next.js

Bug report

Describe the bug

When you navigate to a different route in Next.js 10.0.0 module specific css is reset. This is problematic, because I keep the component mounted for a bit longer to do some animations with framer-motion. In Next.js 9 this was not an issue.

Edit: By the comments it seems like this bug first occured in 9.5.5

To Reproduce

Here is a very basic example. If you run the app in dev mode it works fine, but the production build doesn't. The css is immediately removed if you click on the link.
https://v10-test.vercel.app/

Source code: https://github.com/mxmtsk/v10-test

To keep the page component mounted until the animation is finished, I'm using AnimatePresence from framer-motion

Edit: Here's the same example using Next 9.5.1, where everything works fine: https://v10-test-git-v9.mxmtsk.vercel.app/

Expected behavior

CSS should not be reset.

System information

  • OS: macOS
  • All Browsers
  • Version of Next.js: 10.0.0
  • Version of Node.js: 12.13.1
bug

Most helpful comment

same issue as #17464

All 9 comments

I have the same issue, but even with Next 9.5.5. 馃
Probably the reason is production code splitting for CSS Modules. E.g. global styles & styled-components work fine.

https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css

In production, all CSS Module files will be automatically concatenated into many minified and code-split .css files. These .css files represent hot execution paths in your application, ensuring the minimal amount of CSS is loaded for your application to paint.

@damianslonski Good to know. I upgraded from 9.5.1 where I didn't have the issue.

Has this been working fine when you were still using version 9.5.1?

@dockwarder Yes, here's the same example with 9.5.1
https://v10-test-git-v9.mxmtsk.vercel.app/

@mxmtsk @damianslonski
I have exactly the same issue with version 9.5.5 and later. I ended up with temporary workaround until this would be resolved:

Import critical style modules in _app.tsx, so they are never unmounted on route changes, and pass them through context down to components consuming them:

// _app.tsx
import '../styles/global.scss'

import layoutStyles from '../components/Layout.module.scss'
import heroStyles from  '../components/Hero.module.scss'

const criticalStyles = {
  layoutStyles,
  heroStyles,
}

export const StylesContext = createContext(criticalStyles)

export default function MyApp({ Component, pageProps }: AppProps) {
  const router = useRouter()

  return (
    <StylesContext.Provider value={criticalStyles}>
      <AnimatePresence exitBeforeEnter>
        <Component {...pageProps} key={router.asPath} />
      </AnimatePresence>
    </StylesContext.Provider>
  )
}

// Hero.tsx

// instead of classic import
import styles from './Hero.module.scss'

// use value from context
const { heroStyles } = useContext(StylesContext)

Not nice but it works. Of course I don't mind loading some styles before they are necessary, since they are quite small in size in my case.

I updated to version 10.0.0 yesterday, but haven't had time yet to test if the issue is still present.

Probably related to #17086

same issue as #17464

also have this problem on 9.5.5 and current latest version.
In dev all is ok, production is broken

also have this problem on 9.5.5 and current latest version.
In dev all is ok, production is broken

It started at 9.5.3

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lixiaoyan picture lixiaoyan  路  3Comments

jesselee34 picture jesselee34  路  3Comments

YarivGilad picture YarivGilad  路  3Comments

wagerfield picture wagerfield  路  3Comments

swrdfish picture swrdfish  路  3Comments