0

I'm building a NextJS project using Mantine for UI components and applying our own custom styles using SCSS modules. Also using Typescript. Everything seems to work great however when looking at the build version (not dev) the order in which the styles take effect on the components is delayed. There is a visibile delay in the SCSS modules being applied on the HTML. I'm not sure what is causing this to happen.

When the page loads it looks like this is the order of events:

  1. The Mantine theme and inline CSS styles are applied to the HTML [![Button before SCSS style module is applied][1]][1]
  2. A noticable delay [![Button after SCSS style module is applied][2]][2]
  3. The SCSS modules styles are applied to the HTML

For bad network connections this delay is very noticably.

Here are some notes and code for the NextJS React project:

The SCSS modules are stored beside the component tsx files and scss variables are used as well which are situated in a parent folder.

Header.tsx
Header.modules.scss

An example of the Header code would look like:

Header.tsx

import Link from 'next/link';
import styles from './Header.module.scss';
import { Button } from '@ui/Button/Button';
import { UserCircleIcon } from '@heroicons/react/24/outline';

const Header: React.FC = () => {
  return (
            <Link
              href={www.a.com})}
              passHref
            >
              <Button
                type="button"
                component="a"
                color="gray.1"
                shape="rounded-xl"
                className={[styles.RoundedButton, styles.HeaderButton].join(' ')}
              >
                <UserCircleIcon className={styles.Icon} />
                <span className={styles.RoundedButtonText}>Log In</span>
              </Button>
            </Link>     
  );
};

export default Header;

Header.module.scss

@import 'variables.module.scss';
@import 'uiBreakPoints.module.scss';

.HeaderButton {
  padding: 0 $spacing-sm;
}
.RoundedButton {
  color: $black;
  @include max-media($ui-break-sm) {
    // TODO: Remove !important when SCSS Module fix
    width: 32px !important;
    height: 32px !important;
    padding: 0 !important;
  }
}
.RoundedButtonText {
  margin-left: $spacing-2xs;
  @include max-media($ui-break-md) {
    display: none;
  }
}

next.config.js

const { withSentryConfig } = require("@sentry/nextjs");
const path = require('path');

const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')],
  },
  i18n: {
    locales: ['en-US'],
    defaultLocale: 'en-US',
  },
  env: {
    PUSHER_KEY: process.env.PUSHER_KEY,
    PUSHER_CLUSTER: process.env.PUSHER_CLUSTER,
    PUSHER_APP_ID: process.env.PUSHER_APP_ID,
    PUSHER_SECRET: process.env.PUSHER_SECRET,
  },
  // Optional build-time configuration options
  sentry: {
    // See the 'Configure Source Maps' and 'Configure Legacy Browser Support'
    // sections below for information on the following options:
    //   - disableServerWebpackPlugin
    //   - disableClientWebpackPlugin
    //   - hideSourceMaps
    //   - widenClientFileUpload
    //   - transpileClientSDK
  },
  experimental: {
    images: {
      remotePatterns: [
        {
          protocol: 'https',
          hostname: 'cdn.filestackcontent.com',
        },
      ],
    },
  },
}

const sentryWebpackPluginOptions = {
  // Additional config options for the Sentry Webpack plugin. Keep in mind that
  // the following options are set automatically, and overriding them is not
  // recommended:
  //   release, url, org, project, authToken, configFile, stripPrefix,
  //   urlPrefix, include, ignore

  silent: true, // Suppresses all logs
  // For all available options, see:
  // https://github.com/getsentry/sentry-webpack-plugin#options.
};

module.exports = withSentryConfig(nextConfig, sentryWebpackPluginOptions)``` 


  [1]: https://i.stack.imgur.com/luG0p.png
  [2]: https://i.stack.imgur.com/JhhYK.png
James Finn
  • 366
  • 2
  • 12

1 Answers1

0

I found this guide online, it may helps you!

I think the interesting part is the _document.js file:

import Document from "next/document";
import { createGetInitialProps } from "@mantine/next";

const getInitialProps = createGetInitialProps();
export default class _Document extends Document {
    static getInitialProps = getInitialProps;
}

This code allow Next.js to render components without any delay (I think it doesn't matter if you use SCSS/CSS, jsx/tsx, ect).

After that you have to create another file _app.js (I use .jsx but I think that's the same for .ts / .tsx) and put here your component in a MantineProvider.

P.S. This 2 files are in the pages/ folder.

André
  • 1
  • 1