Marvin_1003
Marvin_1003

Reputation: 74

Nextjs external css not updating on client side page transitions

I am still new to nextjs so i don't know if this is a bug or if i just wrongly implemented it.

I successfully managed to extract all my scss files using this guide: https://github.com/zeit/next-plugins/tree/master/packages/next-sass

Everything works just fine while using server side rendering. External css file gets properly updated and applied, but as soon as i do client side page transitions the new scss import doesnt get injected in the external css file. I also dont want to prefetch every scss file on the initial pageload it should dynamically fetch and update the external file on server side routing and client side routing.

My next.config.js

const getRoutes = require('./routes');
const path = require('path');
const withSass = require('@zeit/next-sass');

module.exports = withSass({
  exportPathMap: getRoutes,
  // useFileSystemPublicRoutes: false,
  cssModules: true,
  cssLoaderOptions: {
    importLoaders: 1,
    localIdentName: "[local]___[hash:base64:5]",
  },
})

Example Component

import { Fragment } from 'react';
import Main from '../components/main';
import style from '../styles/pages/parkett.scss';

const Parkett = () => 
  <Fragment>
    <section className={`section ${style.sec_two_parkett}`}>
      <div className={`sec_text ${style.sec_two_text}`}>
        <h2 className="didonesque_headline">Detailiert</h2>
        <p className="normal_text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p>
      </div>
    </section>
    <section className={`section ${style.sec_three_parkett}`}>
      <div className={`sec_text ${style.sec_three_text}`}>
        <h2 className="didonesque_headline">Erstaunlich</h2>
        <p className="normal_text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat.</p>
      </div>
    </section>
  </Fragment> 

export default () => 
  <Main 
    title="parkett" 
    component={<Parkett />} 
    links={['Treppe', 'Moebel', 'Innenausbau']}
    />

Upvotes: 3

Views: 5578

Answers (2)

Ramo
Ramo

Reputation: 187

Hi i would recommend using styled-jsx-css-loader for loading css into jsx it work fine for me and sass loader to converting sass into css and you can chain them like so in the next.config.js file:

config.module.rules.push({
      test: /\.scss$/,
      use: [
        {
          loader: 'emit-file-loader',
          options: {
            name: 'dist/[path][name].[ext].js',
          },
        },
        {
          loader: 'babel-loader',
          options: {
            babelrc: false,
            extends: path.resolve(__dirname, './.babelrc'),
          },
        },
        'styled-jsx-css-loader',
        // optional if you wanna purify css if you are using bootstrap or a huge css lib
        // {
        //   loader: 'css-purify-webpack-loader',
        //   options: {
        //     includes: [
        //       './pages/*.js',
        //       './components/**/*.js',
        //       './containers/**/*.js',
        //     ],
        //   },
        // },
        {
          loader: 'sass-loader',
          options: {
            sourceMap: dev,
          },
        },
      ],
    });

and you import the sass like this:

import commonStyle from '../styles/common/index.scss';
<style jsx global>
 {commonStyle}
</style>

Upvotes: 1

Bryan Downing
Bryan Downing

Reputation: 15472

Adding the following to the top of my _app.js resolved the issue for me:

// This is a bit of a hack to ensure styles reload on client side route changes.
// See: https://github.com/zeit/next-plugins/issues/282#issuecomment-480740246
if (process.env.NODE_ENV !== 'production') {
  Router.events.on('routeChangeComplete', () => {
    const path = '/_next/static/css/styles.chunk.css'
    const chunksSelector = `link[href*="${path}"]`
    const chunksNodes = document.querySelectorAll(chunksSelector)
    const timestamp = new Date().valueOf()
    chunksNodes[0].href = `${path}?${timestamp}`
  })
}

See the following issues in the next-plugins repo for some background:

Upvotes: 1

Related Questions