Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sass @use statements don't work #11610

Closed
nicholaschiang opened this issue Apr 2, 2020 · 11 comments
Closed

Sass @use statements don't work #11610

nicholaschiang opened this issue Apr 2, 2020 · 11 comments
Labels
good first issue Easy to fix issues, good for newcomers

Comments

@nicholaschiang
Copy link
Contributor

Bug report

Describe the bug

A clear and concise description of what the bug is.

In my global.scss file that is imported by src/pages/_app.tsx:

@use '@material/textfield/mdc-text-field';
@use '@material/select/mdc-select';

body {
  margin: 0;
  padding: 0;
  outline: 0;
  overflow-x: hidden;
}

Those @use statements fail however because the default sass-loader cannot find those stylesheets:


[ error ] ./src/pages/global.scss (./node_modules/css-loader/dist/cjs.js??ref--5-oneOf-6-1!./node_modules/next/dist/compiled/postcss-loader??__nextjs_postcss!./node_modules/resolve-url-loader??ref--5-oneOf-6-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-6-4!./src/pages/global.scss)
SassError: Can't find stylesheet to import.
   ╷
24 │ @use "@material/density/functions" as density-functions;
   │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵
  node_modules/@material/textfield/_mixins.scss 24:1         @use
  node_modules/@material/textfield/mdc-text-field.scss 23:1  @use
  /home/nchiang/repos/covid-tutoring/src/pages/global.scss 1:1                                                  root stylesheet

This would make sense, but I also included the node_modules directory where the imported stylesheets reside to our next.config.js (using the recently implemented fix):

const path = require('path');

module.exports = {
  sassLoaderOptions: {
    sassOptions: {
      includePaths: [path.resolve(__dirname, 'node_modules')],
    },
  },
  webpack(config) {
    config.module.rules.push({
      test: /\.svg$/,
      use: ['svg-url-loader'],
    });
    return config;
  },
};

And it still doesn't work.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Clone this repository
  2. Install our dependencies with npm i
  3. Run npm run dev or npx next
  4. See error

Expected behavior

A clear and concise description of what you expected to happen.

The sass-loader used by Next.js should know to look in our node_modules folder for those stylesheets.

System information

  • OS: Ubuntu 18.04.2
  • Version of Next.js: ^9.3.4
  • Version of Node.js: v12.16.1

Additional context

Add any other context about the problem here.

You should also work on making this documentation more clear that Next.js has built-in support for Sass (see this issue for more info).

@nicholaschiang
Copy link
Contributor Author

nicholaschiang commented Apr 2, 2020

Update: it looks like (with that modified next.config.js) sass-loader was able to find @material/textfield/mdc-text-field but it's still throwing an error about finding the stylesheets that those styles (the @material/textfield/mdc-text-field ones) @use:

5-oneOf-6-3!./node_modules/sass-loader/dist/cjs.js??ref--5-oneOf-6-4!./src/pages/global.scss)                                                                                                         
SassError: Can't find stylesheet to import.                                                                                                                                                           
   ╷                                                                                                                                                                                                  
24 │ @use "@material/density/functions" as density-functions;                                                                                                                                         
   │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   ╵
  node_modules/@material/textfield/_mixins.scss 24:1         @use                       
  node_modules/@material/textfield/mdc-text-field.scss 23:1  @use
  /home/nchiang/repos/covid-tutoring/src/pages/global.scss 1:1                                                  root stylesheet

And I've verified that those stylesheets are indeed there in the node_modules path specified in sassLoaderOptions.sassOptions.includePaths:

nchiang@eevee ~/repos/covid-tutoring/node_modules/@material (master) $ ls
animation  density            floating-label  menu             rtl        theme
base       dom                icon-button     menu-surface     select     touch-target
button     elevation          line-ripple     notched-outline  shape      typography
card       feature-targeting  list            ripple           textfield
nchiang@eevee ~/repos/covid-tutoring/node_modules/@material (master) $ ls density/
_functions.import.scss  _functions.scss  _index.scss  LICENSE  package.json  README.md  _variables.import.scss  _variables.scss

@timneutkens timneutkens added good first issue Easy to fix issues, good for newcomers help wanted labels Apr 3, 2020
@jonathansamines
Copy link

@nicholaschiang I have usually imported stylesheets from node modules by appending ~ as a prefix (don't remember why that is necessary though)

@use "~@material/density/functions" as density-functions;

@nicholaschiang
Copy link
Contributor Author

Hey @jonathansamines that would be sass-loader's convention.

But this is happening when the stylesheets that I'm using are @use-ing other stylesheets and I don't want to modify those dependencies.

@nicholaschiang
Copy link
Contributor Author

Just FYI I just cloned this Sass example and added a basic @use statement in components/hello-world.module.scss.

That resulted in exactly the same error as seen above. Because of this IMO Next.js cannot say it has built-in Sass support. This is a real blocker for our development workflows. It'd be nice to have more detailed documentation on how you "support it" out-of-box.

@nicholaschiang
Copy link
Contributor Author

Actually, after a deeper dive into #11063 it looks like I implemented my configuration incorrectly (you guys seriously have to work on your documentation). This next.config.js seems to be working:

const path = require('path');

module.exports = {
  experimental: {
    sassOptions: {
      includePaths: [path.resolve(__dirname, 'node_modules')],
    },
  },
};

I'm going to keep this issue open but now I'm only asking for improved documentation for how to use/enable experimental features. You should also consider adding documentation to your website for such experimental features so that developers don't have to spend days searching through old issues, discussions, and PRs.

@iksent
Copy link

iksent commented Apr 14, 2020

@nicholaschiang, hello!

I think, that to use SASS and CSS options, you need the following code:

const withSass = require('@zeit/next-sass')

module.exports = withSass({
  cssModules: true,
  sassLoaderOptions: {
    // Resolving SASS absolute imports
    includePaths: [path.resolve(__dirname, 'src')],
  },
  cssLoaderOptions: {
    localIdentName: '[hash:base64]',
  },
  ...
}

It works for me and resolves my absolute imports for local folders within the @use.

BUT: I have problems with CSS import ordering in production. Found similar issues, and I'm trying to resolve this problem.

@nicholaschiang
Copy link
Contributor Author

Yup, @iksent it seems like you're using the old plugin that's no longer needed for Sass support; Next.js now has built-in Sass support (see my previous comments for more info).

@iksent
Copy link

iksent commented Apr 14, 2020

Yes, that's true.
I tried built-in support and it works too in dev-mode, but my problem with CSS imports in production was not resolved...

@smurrayatwork
Copy link

For anyone else that's trying to use this with dart sass' js implementation for things like @use support and sass modules, if you have -any- other node module that has a dependency on node-sass, the default next setup will use node-sass instead of sass. Locally I've fixed it by doing the following:

// example next.config.js
module.exports = {
webpack(config, options) {
  config.module.rules.forEach(rule => {
          if (rule.oneOf) {
            const nestedScss = rule.oneOf.find((one) => {
              return one.test
                && 'some.scss'.match(one.test) 
                && one.issuer 
                && one.issuer.include 
                && one.issuer.include.includes('_app');
            });
            if (nestedScss) {
              const sassLoader = nestedScss.use.find(u => u.loader.includes('sass-loader'));
              // Set implementation to sass instead of node-sass here.
              sassLoader.options.implementation = require('sass');
            }
          }
        })
  }
}

You'll then need to import your scss files in _app.js.

@Timer Timer removed the help wanted label Jun 3, 2020
@nicholaschiang
Copy link
Contributor Author

Closing this as it was addressed a while ago.

@balazsorban44
Copy link
Member

This issue has been automatically locked due to no recent activity. If you are running into a similar issue, please create a new issue with the steps to reproduce. Thank you.

@vercel vercel locked as resolved and limited conversation to collaborators Jan 30, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
good first issue Easy to fix issues, good for newcomers
Projects
None yet
Development

No branches or pull requests

7 participants