Skip to content
This repository has been archived by the owner on Jul 6, 2021. It is now read-only.

Cant change page with 'next/link' & 'next-css' #282

Closed
standy opened this issue Sep 24, 2018 · 221 comments
Closed

Cant change page with 'next/link' & 'next-css' #282

standy opened this issue Sep 24, 2018 · 221 comments

Comments

@standy
Copy link

standy commented Sep 24, 2018

This is bug report

Link does not work with css-module imported. That happens when page with Link has no css, and linked page has. No errors in console, so im not sure about reasons, but there is minimal repo to reproduce:
https://github.com/standy/next-css-error

Bug appears in next@7.0.0 + next-css@1.0.1,
Older next@6.1.2 + next-css@0.2.0 works fine

@Dynogic
Copy link

Dynogic commented Sep 26, 2018

I have the exact same issue, on the exact same versions as well.

Confirmed work around: make every page import some css.

@virzak
Copy link

virzak commented Sep 26, 2018

Was trying hard to determine what was causing that. Thanks for reporting @Dynogic and @standy

@Enalmada
Copy link
Contributor

Enalmada commented Oct 3, 2018

Same problem except with next-css. Clicking links importing less just don't respond. My workaround was to stop using less/css. Note this ticket vercel/next.js#5264 (comment) suggests you can import blank in _app.js.

@kylemh
Copy link
Contributor

kylemh commented Oct 3, 2018

https://spectrum.chat/thread/2183fc55-236d-42cb-92b9-3ab10acc6303?m=MTUzODU2NDg2ODA2Mg==

Next team is aware and working on it! It's complex and will take time.

Importing an empty stylesheet into _app.js nor importing a stylesheet on every page resolved the issue for me locally.

@nisargrthakkar
Copy link

@kylemh I tried Importing an empty stylesheet into _app.js nor importing a stylesheet on every page resolved the issue for me locally. but still not working

@kylemh
Copy link
Contributor

kylemh commented Oct 15, 2018

It's a strategy some have professed, but it doesn't resolve anything for me - just like you.

@popuguytheparrot
Copy link

Same problem

@timneutkens
Copy link
Member

@kylemh / others could you try @zeit/next-css@canary? It holds #315

@kylemh
Copy link
Contributor

kylemh commented Oct 22, 2018

I would fuckin' love to ❤️

@aserranom
Copy link

@timneutkens The error is gone, great job! However when changing routes I'm not getting that new route's style... is anyone else having that issue?

Unfortunately I have to go and won't be able to troubleshoot it further or provide additional details today.

@kylemh
Copy link
Contributor

kylemh commented Oct 22, 2018

^ this precisely.

It doesn't look like I'm getting more CSS files per route - just on initial load.

SSR gets all styles properly.

@nisargrthakkar
Copy link

Same issue with @zeit/next-css@canary not get css load on route change

@kylemh
Copy link
Contributor

kylemh commented Oct 23, 2018

That being said, I'd say this issue can be closed and another can be made on route-based code splitting withCSS with CSS Modules + PostCSS (at least for me) not working as desired?

@plag
Copy link
Contributor

plag commented Oct 23, 2018

Yes, on route change issue still present. Long time i used next6 with old next-css and regulary gets not loaded styles on route change. After refresh page it works as expected even on route change.
On 7 version it reproduced on every page change (not sometimes as next6).
But if you 1) load first page 2) transition to next page (gets not loaded styles) 3) refresh page - then you take working styles on both pages.

Looks like styles compilation is long process and delayed and page do not have time for take it and apply. After refresh page styles already precompiled and applied immediatelly.

@plag
Copy link
Contributor

plag commented Oct 23, 2018

my workaround this bug (on latest canary)

somewhere in _app.js

import Router from 'next/router';

Router.events.on('routeChangeComplete', () => {
  if (process.env.NODE_ENV !== 'production') {
    const els = document.querySelectorAll('link[href*="/_next/static/css/styles.chunk.css"]');
    const timestamp = new Date().valueOf();
    els[0].href = '/_next/static/css/styles.chunk.css?v=' + timestamp;
  }
})

on every page reloads css after router change

@popuguytheparrot
Copy link

my workaround this bug (on latest canary)

somewhere in _app.js

...
import Router from 'next/router';
...
Router.onRouteChangeComplete = () => {
  if (process.env.NODE_ENV !== 'production') {
    const els = document.querySelectorAll('link[href*="/_next/static/css/styles.chunk.css"]');
    const timestamp = new Date().valueOf();
    els[0].href = '/_next/static/css/styles.chunk.css?v=' + timestamp;
  }
}

on every page reloads css after router change

look like bicyclecode

@stian-midlertidig
Copy link

@plag thanks so much for sharing that! 😄

@timneutkens
Copy link
Member

@plag I've updated your comment to use Router.events instead: https://github.com/zeit/next.js#router-events

@zhanglin-doudou
Copy link

I had found a way to solve it. Not really perfect.

I have used a component Layout in every page.

import React, { Component } from 'react';
import Head from 'next/head';

export default class Layout extends Component {
  render() {
    const { children, title, style, className } = this.props;

    return (
      <div className={'main-layout col ' + className} style={style}>
        <Head>
          <title>{title}</title>
          {process.env.NODE_ENV !== 'production' && (
            <link rel="stylesheet" type="text/css" href={'/_next/static/css/styles.chunk.css?v=' + Date.now()} />
          )}
        </Head>
        <div className="main-content">{children}</div>
      </div>
    );
  }
}

@popuguytheparrot
Copy link

I had found a way to solve it. Not really perfect.

I have used a component Layout in every page.

import React, { Component } from 'react';
import Head from 'next/head';

export default class Layout extends Component {
  render() {
    const { children, title, style, className } = this.props;

    return (
      <div className={'main-layout col ' + className} style={style}>
        <Head>
          <title>{title}</title>
          {process.env.NODE_ENV !== 'production' && (
            <link rel="stylesheet" type="text/css" href={'/_next/static/css/styles.chunk.css?v=' + Date.now()} />
          )}
        </Head>
        <div className="main-content">{children}</div>
      </div>
    );
  }
}

How ur layout will work in _app.js
For example

<Container>
  <Layout>
    <Component>
  </Layout>
</Container>

@zhanglin-doudou
Copy link

I had found a way to solve it. Not really perfect.
I have used a component Layout in every page.

import React, { Component } from 'react';
import Head from 'next/head';

export default class Layout extends Component {
  render() {
    const { children, title, style, className } = this.props;

    return (
      <div className={'main-layout col ' + className} style={style}>
        <Head>
          <title>{title}</title>
          {process.env.NODE_ENV !== 'production' && (
            <link rel="stylesheet" type="text/css" href={'/_next/static/css/styles.chunk.css?v=' + Date.now()} />
          )}
        </Head>
        <div className="main-content">{children}</div>
      </div>
    );
  }
}

How ur layout will work in _app.js
For example

<Container>
  <Layout>
    <Component>
  </Layout>
</Container>

I am not using Layout in _app.js. Every single page has a container with Layout.
e.g. :

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Layout from '../components/layout/Layout';

class FeedbackSuccess extends Component {
  render() {
    return <Layout title="操作成功">操作成功</Layout>;
  }
}

export default connect()(FeedbackSuccess);

@dankythuat
Copy link

Same issue, anyone can resolve it?

@cherniavskii
Copy link

@tuanhuu
While waiting for fix, the simplest workaround is to create empty css file in static catalog and import it in _app.jsx

@mattvb91
Copy link

mattvb91 commented Mar 21, 2020

@shirshendubhowmick are you using styled components lib? I had the same issue with components and had to rollback styled components to v4 as it was clearing the <style> tag on a <Link> click.

@shirshendubhowmick
Copy link

@mattvb91 No i am not using styled components. I am using mini-css-extract-plugin to load my CSS.

@gaurav5430
Copy link

I am having this issue with next@9.2.1.

This fix worked for me: sheerun/extracted-loader#11.
It also works much better than the routeChangeComplete hack and causes no FOUC flashes.

I guess the root cause of this issue is regarding HMR handling of next and the mini-css-extract-plugin

@igl
What was your issue?
Was the route not loading at all?
OR
Was the route specific css not loading on client side routing?

How did sheerun/extracted-loader#11 solve your problem?

@sangdth
Copy link

sangdth commented Apr 5, 2020

I have exactly the same issue like @shirshendubhowmick. It works fine on production, and in development, if I copy/paste the exact url it will work ok, but not load the page's scss if I navigate by Link.

My next.config.js:

  withCSS(
    withSass({
    cssModules: true,
    cssLoaderOptions: {
      url: false,
      importLoaders: 2,
      esModule: true,
      localIdentName: '[local]-[hash:base64:5]',
      getLocalIdent: (ctx, ident, name, opts) => {
        if (ctx.resourcePath.includes('node_modules')) {
          return name;
        } else {
          return getDefault(ctx, ident, name, opts);
        }
      }
    },
...

@shirshendubhowmick
Copy link

@sangdth I worked around this, by adding a route change listener in _app.js.

This route change listener get registered on development mode only. On every route change it adds a link tag with the link to necessary CSS file.

My code somewhat looks like below:

    if (ENV === 'development' || ENV === 'local') {
      Router.events.on('routeChangeComplete', (url) => {
        const fileName = url.split('/')[1];
        const linkTag = document.createElement('link');
        linkTag.setAttribute('rel', 'stylesheet');
        linkTag.setAttribute('href', `/_next/static/css/static/development/pages/${fileName}.js.css?ts=${new Date().valueOf()}`);
        document.head.appendChild(linkTag);
      });
    }

@igl
Copy link

igl commented Apr 5, 2020

What was your issue?

#263 was my issue. CSS would not load after route transitioning.

@chornos13
Copy link

@sangdth I worked around this, by adding a route change listener in _app.js.

This route change listener get registered on development mode only. On every route change it adds a link tag with the link to necessary CSS file.

My code somewhat looks like below:

    if (ENV === 'development' || ENV === 'local') {
      Router.events.on('routeChangeComplete', (url) => {
        const fileName = url.split('/')[1];
        const linkTag = document.createElement('link');
        linkTag.setAttribute('rel', 'stylesheet');
        linkTag.setAttribute('href', `/_next/static/css/static/development/pages/${fileName}.js.css?ts=${new Date().valueOf()}`);
        document.head.appendChild(linkTag);
      });
    }

looks like your document head get bigger and bigger ;)

@shirshendubhowmick
Copy link

@chornos13 Only in case of development mode.

@transiient
Copy link

This is still broken in development mode, two years later. Very, very annoying bug which is difficult to find on Google. The workaround posted by @Dynogic still works.

@timneutkens
Copy link
Member

This is still broken in development mode, two years later. Very, very annoying bug which is difficult to find on Google. The workaround posted by @Dynogic still works.

This was fixed by introducing built-in CSS/Sass support into Next.js as said multiple times in this thread: #282 (comment)

@transiient
Copy link

transiient commented May 9, 2020 via email

@shirshendubhowmick
Copy link

@timneutkens The problem still exists if we want to have our own CSS loading pipeline.

@timneutkens
Copy link
Member

@timneutkens The problem still exists if we want to have our own CSS loading pipeline.

If you want to roll your own css loading you have to mirror the implementation that is currently in the Next.js core, however I can't imagine a good reason to not use the built-in support as-is as it prevents a ton of common pitfalls when compiling CSS (eg it splits chunks per-page for CSS modules and forces global css to be global).

@shirshendubhowmick
Copy link

shirshendubhowmick commented May 9, 2020

We use CSS modules along with couple of postCSS plugins, also we have some global CSS which gets loaded without CSS modules.

So we need to specify how to load our different types of CSS, thats why a custom CSS loading pipeline is necessary

@timneutkens

@chornos13
Copy link

chornos13 commented May 11, 2020

@timneutkens The problem still exists if we want to have our own CSS loading pipeline.

If you want to roll your own css loading you have to mirror the implementation that is currently in the Next.js core, however I can't imagine a good reason to not use the built-in support as-is as it prevents a ton of common pitfalls when compiling CSS (eg it splits chunks per-page for CSS modules and forces global css to be global).

@timneutkens I need to use less module, currently only css/sass support built-in, that's why I need to add custom css loader, but it's broken like this issue

@saibs
Copy link

saibs commented May 11, 2020

For example we use antd and modify the theme, so we have to use the less loader and css loader.

@josefanostylus
Copy link

Is ditching next/css , next/less and adding the stylesheets in _app.js still the best solution to this? or there's a fix for this issue ?

@raindecastro
Copy link

Same here, I have to use a different loader too so I can accommodate antd for theme modifications.

@yadielar
Copy link

yadielar commented Jun 16, 2020

@timneutkens The problem still exists if we want to have our own CSS loading pipeline.

If you want to roll your own css loading you have to mirror the implementation that is currently in the Next.js core, however I can't imagine a good reason to not use the built-in support as-is as it prevents a ton of common pitfalls when compiling CSS (eg it splits chunks per-page for CSS modules and forces global css to be global).

Hi @timneutkens, first of all thanks for all the work and patience trying to solve this issue.

Does your comment above mean Next.js does not support using CSS-in-JS libraries like Treat, Linaria, Astroturf, etc. that offer static CSS extraction?

I don't want to interpret your comments the wrong way or put any words in your mouth, I'm just wondering what's your take on using CSS-in-JS libraries like those I mention that extract CSS in some manner.

@babbarankit

This comment has been minimized.

@tufail
Copy link

tufail commented Sep 27, 2020

I have exactly the same issue like @shirshendubhowmick. It works fine on production, and in development, if I copy/paste the exact url it will work ok, but not load the page's scss if I navigate by Link.

My next.config.js:

  withCSS(
    withSass({
    cssModules: true,
    cssLoaderOptions: {
      url: false,
      importLoaders: 2,
      esModule: true,
      localIdentName: '[local]-[hash:base64:5]',
      getLocalIdent: (ctx, ident, name, opts) => {
        if (ctx.resourcePath.includes('node_modules')) {
          return name;
        } else {
          return getDefault(ctx, ident, name, opts);
        }
      }
    },
...

I am having the same issue. Is it resolved ?

@shirshendubhowmick
Copy link

Looks like this issue is still there with v10.0.3

@timneutkens
Copy link
Member

Hey! I'm going to close this issue as @zeit/next-css is deprecated in favor of the built-in CSS and Sass support which solves this issue and many others, thanks for your understanding 🙏

@shirshendubhowmick
Copy link

@timneutkens I doubt that this problem is related to @zeit/next-css. I am using NextJS v10+, without @zeit/next-css and anyother external library. I have just used next config to write my own CSS pipeline, the problem exists there also.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests