create-react-app 2.0, how to use absolute path import in sass/scss files?

Created on 20 May 2018  路  22Comments  路  Source: facebook/create-react-app

Is this a bug report?

No

The problem

I am using creacte-react-app 2.0.0-next.66cc7a90, which already has support for Sass/Scss files

however with default relative import in Sass/Scss files, i have to use code like
@import "../../../../../styles/variables/_variables.scss";

instead I want to use absolute import so i can import with code
@import "styles/variables/_variables.scss";

I know one way to acheve so is to update options

{
   loader: "sass-loader",
   options: {
        includePaths: ["absolute/path/a", "absolute/path/b"]
 }

but I want to do it without ejecting, how can i do it? using react-app-rewired?

stale

Most helpful comment

@Timer This is an issue when using SCSS files from NPM packages where they also get SCSS files from other packages.

A very good example is @material:
You will need to import their SCSS like so:

@import '~@material/button/mdc-button';

But inside their SCSS file they have:

@import "@material/ripple/common";
@import "@material/ripple/mixins";
@import "./mixins";
@import "./variables";

So the build breaks as they do not have the ~. On their side, it makes sense as that's how SASS works. But sass-loader makes it complex as they need the ~ to go look inside the node_modules.

For CRA, including this option fixes this problem (tested on my local):

includePaths: ["node_modules"]

All 22 comments

Start read from https://github.com/facebook/create-react-app/pull/4195#issuecomment-383328415

I think implementation is not that complex. @gaearon @Timer what do you think of re-using NODE_PATH as SCSS includePaths?

I'm good with adding NODE_PATH, but I have hesitations about its implications; afaik it's suggested not to use includePaths in the sass-loader docs.

@Timer kinda weird. I have been using this option for years, works like a charm.
I can open a PR if you're okay with that.

I was using NODE_PATH just fine with: @import "styles/footer.scss"; in my scss file.

modified:   footer.scss
Untracked files:
    ../../styles/footer.scss
> cat footer.scss 
@import "styles/footer.scss";

Is this issue related to #4651?

I'm successfully using absolute imports with ~ and NODE_ENV set in .env

/.env:

NODE_PATH=src/

given that /src/styles/variables.scss exists, in any .scss file:

@import ~styles/variables`

works fine with in v2.0.

@justo This is fine when you have full control over the scss files. It won't work for existing component libraries that don't support the ~ syntax for imports.

@Timer This is an issue when using SCSS files from NPM packages where they also get SCSS files from other packages.

A very good example is @material:
You will need to import their SCSS like so:

@import '~@material/button/mdc-button';

But inside their SCSS file they have:

@import "@material/ripple/common";
@import "@material/ripple/mixins";
@import "./mixins";
@import "./variables";

So the build breaks as they do not have the ~. On their side, it makes sense as that's how SASS works. But sass-loader makes it complex as they need the ~ to go look inside the node_modules.

For CRA, including this option fixes this problem (tested on my local):

includePaths: ["node_modules"]

I agree with @fbarbare. I have the same issue with @material. I extended the getStyleLoaders function to take an options object with included includePaths: ["node_modules"]. This worked well for my project.

I understand the philosophy of the project is to prefer convention over configuration. The default behavior works for most cases. However, there are situations where the default behavior does not work. Either, this is enabled by default or put behind a feature flag considering the issues mentioned above by @Timer. Thoughts?

I am facing the same issue with @material. Is there any way to solve this without ejecting?

I would like to add that adding a .env or .env.development (and .env.production) file at the project root with SASS_PATH=src allowed me to use @import dir_in_src/some_file.

For multiple sass paths, you should be able to use SASS_PATH=node_modules:src.

I confirm the solution @jayantbh provided, it worked flawlessly!

@gudh Does this solution work for you? Can we close this issue now?

@iansu I think it does, last week I also had this issue and the way I solved was following the tutorial https://github.com/material-components/material-components-web-react with some changes

  • First I performed step 1 and 2.

  • Then for step 3 I just followed @jayantbh solution exactly so I created the files env. and env.production and wrote SASS_PATH=node_modules:src in both files, then I installed node-sass with yarn add node-sass, then I rename the src/App.css file to src/App.scss and finally added the following line

// ./src/App.scss

@import "@material/react-button/index.scss";

...
  • Finally the step 4 was the same.

I used ubuntu 18.04.1 LTS and CRA 2.1.1.

@LuisAlbertoVasquezVargas I tried this solution but I still get the following error:
File to import not found or unreadable: @material/react-button/index.scss.
in srcApp.scss

I also tried setting the the SASS_PATH as an environment variable in my user account, with no success.
I have @material installed under node_modules, using Windows 10.

@Vilvalas I think I forgot to add the tilde "~" before @material in those instructions, my bad, https://github.com/LuisAlbertoVasquezVargas/material-testing/blob/4d45e75429db817813ffa92ceb91b7c9038400b6/src/App.scss#L55
Let me double-check and I'll tell you, I invite you to try to put that tilde.

@LuisAlbertoVasquezVargas If I use the tilde the initial import from App.scss works.
But then the imports from within node_modules fail. E.g. "mdc-button.scss" tries to import the following dependencies (which fail)
@import "@material/ripple/common";
@import "@material/ripple/mixins";

@Vilvalas I see what happened, days before I tried different approaches to set up a simple app and some things were omitted and others taken for granted. Now this post will replace the previous one.
Basicaly I modified the current guide Guide.

Step 1: Create a blank react app

npx create-react-app my-app
cd my-app
npm start

Then if everything goes fine press Ctrl + c to turn off the local server.

Step 2: Install React Button Component

npm install @material/react-button

Step 3: Using Sass

Add environment variable
export SASS_PATH=./node_modules

_NOTE:_ I am not very sure how environment variable works, I think that this export is temporary if you want to add it permanently, read the tutorial adding environment variables.

Install SASS
npm install node-sass
Rename your css file

Rename your src/App.css file to src/App.scss.

// ./src/App.scss

@import "@material/react-button/index.scss";

...

Step 4: Replace code

Open ./src/App.js. Then replace the boilerplate App code (entire file) with this code:

import React, {Component} from 'react';
import Button from '@material/react-button';

import './App.scss';
// add the appropriate line(s) in Step 3a if you are using compiled CSS instead.

class App extends Component {
  render() {
    return (
      <div>
        <Button
          raised
          onClick={() => console.log('clicked!')}
        >
          Click Me!
        </Button>
      </div>
    );
  }
}

export default App;
Run your App
npm start

UPD: There is no need to add tildes anymore.

Can confirm this works, thank you. I'm not really sure what the problem in my project was.

I think the optimal solution would be to create a .env file with
SASS_PATH=./node_modules

like @jayantbh commented earlier.

This issue has been automatically marked as stale because it has not had any recent activity. It will be closed in 5 days if no further activity occurs.

This issue has been automatically closed because it has not had any recent activity. If you have a question or comment, please open a new issue.

Was this page helpful?
0 / 5 - 0 ratings