question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Global Sass imports don't work when you use variables, mixins, functions, etc!

See original GitHub issue

I’ve been working in Gatsby for a while, and recently did a project in Nuxt.js, and I’d love to compare and hope for a similar feature in Next.js. I recently read the blog about Sass imports in version 9.3 and I thought now would be a great time to test out Next.js with a new project.

I would love to know if this is a bug that’s getting fixed, or there are similar “community” packages that solve this problem, and/or if Next.js will implement this in the future ever?

Bug report

Global imports for Sass work via pages/_app.js, but the Sass mixins, variables, functions, etc don’t apply globally as the styles do.

You can achieve this in Nuxt.js like so in the nuxt.config.js:

export default {
  modules: [
    '@nuxtjs/style-resources',
  ],
  // for global imports
  css: ['~/styles/normalize.scss', '~/styles/typography.scss', '~/styles/global.scss'],
  // for utility imports
  styleResources: {
    scss: [
      '~/styles/abstracts/_mixins.scss',
      '~/styles/abstracts/_variables.scss',
      '~/styles/abstracts/_functions.scss'
    ]
  },
}

and in Gatsby via the gatsby.config.js (but unfortunately they don’t have global Sass imports)

module.exports = {
  plugins: [
    {
      resolve: `gatsby-plugin-sass`,
      options: {
        data: `
            @import './src/styles/_variables.scss';
            @import './src/styles/_mixins.scss';
            @import './src/styles/_functions.scss';
          `,
        includePaths: ['./src/styles/']
      }
    }
  ]
};

I tried to achieve the same thing in Next.js by adding this to the pages/_app.js

import '../styles/functions.scss';
import '../styles/keyframes.scss';
import '../styles/mixins.scss';
import '../styles/variables.scss';

// these work properly IF there's no variables referencing the above, otherwise they'll error
import '../styles/global.scss';
import '../styles/typography.scss';
import '../styles/normalize.scss';

export default function MyApp({ Component, pageProps }) {
  return <Component {...pageProps} />
}

I tried this method but next-sass wasn’t playing well with built-in sass, so it doesn’t seem like it’s backwards compatible?

And when I try to just import the file in a page or component it will then just tell me to import via pages/_app.js which doesn’t work.

CleanShot 2020-04-02 at 18 01 12@2x

I feel like I’m missing something… (sorry if I am), but I’m not understanding why all these other issues are closed. I’m wondering why I can’t use Sass features but yet there’s documentation about use Sass modules?

There also claims to be a workaround here but provides no context on how to implement that or where to put the code? I would love if there was some more documentation around this. I would love to be able to use these Sass core features in Next!

Hopefully someone can help me out, thanks!

System information

  • Latest macOS Catalina
  • Next 9.3.4

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:6
  • Comments:15 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
7iomkacommented, May 16, 2020

My workaround:

webpack: (config) => {
  // Issue: https://github.com/zeit/next.js/issues/10339#issuecomment-596966509
  config.module.rules.map((rule) => {
    if (rule.oneOf) {
      rule.oneOf.find((configRule) => {
        if (Array.isArray(configRule.use)) {
          configRule.use.forEach((loaderItem) => {
            const isSassRule = loaderItem.loader && loaderItem.loader.includes('sass-loader');
            const isCssLoader = loaderItem.loader && loaderItem.loader.includes('css-loader');
            if (isSassRule) {
              configRule.use.push({
                loader: 'sass-resources-loader',
                options: {
                  // globally needed mixins, functions, etc.
                  // eslint-disable-next-line global-require
                  resources: require('./src/scss/scss-resources.js'),
                },
              });
            }
            if (isCssLoader) {
              if (loaderItem.options && loaderItem.options.modules) {
                // Remove 'pure' mode for css-modules, add new rules
                // TODO: need tests
                // Sources: https://github.com/zeit/next.js/blob/canary/packages/next/build/webpack/config/blocks/css/index.ts#L101
                delete loaderItem.options.modules.mode;
              }
              // Export '.class-name' as { className }
              loaderItem.options.localsConvention = 'camelCase';
            }
          });
        }
      });
    }
  });

  return config;
}

scss-resources.js

const path = require('path');

const resources = [
  // general functions
  'core/_functions.scss',
  // general color palette (opt)
  'core/_palette.scss',
  // general core variables (can be overridden with theme-settings)
  'core/_settings.scss',
  // media-queries mixins helper
  'core/helpers/_include-media.scss',
  // common mixins
  'core/mixins/_common-mixins.scss',
  // utility mixins
  'core/mixins/_utility-mixins.scss',
];
module.exports = resources.map(file => path.resolve(__dirname, file));
3reactions
canrozanescommented, Apr 4, 2020

If i’m understanding your issue correctly, whenever you’d like to consume sass variables and mixins in a .module.scss file, you have to individually import those partials to that specific .module.scss file.

The following works for me:

_colors.scss

$orange: #d36816;

button.module.scss

@import "../styles/partials/colors.scss";  

.button {
  border: 1.5px solid $orange;
}

button.js

import styles from './button.module.scss'

const Button = () => <button className={styles.button}/>

export default Button

For this to work all you need is to npm install sass.

That being said it’d be nice if we could import variable partials into _app.js file and be able to refer to them globally across different .module.scss file without having to repeatedly import them.

Read more comments on GitHub >

github_iconTop Results From Across the Web

SASS - use variables across multiple files
My point is that I don't need to import variable.scss in any file, ... component file needing a function module @use 'functions.scss';.
Read more >
How to import Sass/SCSS mixins global?
I import the two .scss files in the App.js so I can access the classes/mixins/variables global. But only the classes are accessible.
Read more >
Sass: @use
Members (variables, functions, and mixins) loaded with @use are only visible in the stylesheet that loads them. Other stylesheets will need to write...
Read more >
Sass @import and Partials
You can also import CSS files. The @import directive imports the file and any variables or mixins defined in the imported file can...
Read more >
Features In-Depth | Less.js
Less extends CSS with dynamic behavior such as variables, mixins, operations and ... You can easily treat properties like variables using the $prop...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found