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

CRA 4 failed to make SASS variables available to JavaScript (OK with CRA 3.x) #10047

Closed
guicara opened this issue Nov 9, 2020 · 18 comments · Fixed by #10511
Closed

CRA 4 failed to make SASS variables available to JavaScript (OK with CRA 3.x) #10047

guicara opened this issue Nov 9, 2020 · 18 comments · Fixed by #10511

Comments

@guicara
Copy link

guicara commented Nov 9, 2020

How to read SASS variables in JavaScript?

With Create React App 3.x it is possible to make SASS variables available to JavaScript. To make variables available, we simply need to export them with the :export syntax. For example:

$color-black: #000000;

:export {
    colorBlack: $color-black;
}

We can then import the SCSS file into JavaScript to access the variables defined in the file:

import colors from './template/colors.scss';

console.log('colors', colors.colorBlack); // will output #000000 in the console

It can be really useful to export SASS variables. For example, in our projects, we often create custom themes for Material UI to change the colors, the typography, the components... and will also use SASS. Therefore, we can directly import SASS variables in our Material UI theme:

import { createMuiTheme } from '@material-ui/core/styles';

const theme = createMuiTheme({
  palette: {
    primary: {
      main: colors.colorBlack,
    },
    secondary: {
      main: colors.colorBlue,
    },
  },
});

As far as I know, react-scripts use css-loader as a dependency to configure webpack to enable this feature.

More info about :export here and here.

Describe the bug

Create Rect App 4.0.0 cannot read the exported variables. The variables are undefined.

Did you try recovering your dependencies?

Yes.

Which terms did you search for in User Guide?

N/A

Environment

Output of npx create-react-app --info:

Environment Info:

  current version of create-react-app: 4.0.0
  running from /home/user/.npm/_npx/119730/lib/node_modules/create-react-app

  System:
    OS: Linux 5.4 Ubuntu 20.04.1 LTS (Focal Fossa)
    CPU: (8) x64 Intel(R) Core(TM) i7-7700HQ CPU @ 2.80GHz
  Binaries:
    Node: 12.18.1 - ~/.nvm/versions/node/v12.18.1/bin/node
    Yarn: 1.22.5 - /usr/bin/yarn
    npm: 6.14.5 - ~/.nvm/versions/node/v12.18.1/bin/npm
  Browsers:
    Chrome: 86.0.4240.111
    Firefox: 82.0.2
  npmPackages:
    react: ^17.0.1 => 17.0.1 
    react-dom: ^17.0.1 => 17.0.1 
    react-scripts: 4.0.0 => 4.0.0 
  npmGlobalPackages:
    create-react-app: Not Found

Steps to reproduce

N.B: You can clone my demo repositories (see below) if you don't want to manually reproduce the bug.

Requirements: you need to setup Sass in Create React App. Please follow the documentation here.

  1. Create a SCSS file
  2. Export a variable with the :export keyword (see example above)
  3. On a JavaScript file or a React Component, import the SCSS file
  4. Try to read the variable

Expected behavior

The value of the SASS variable should be available in JavaScript.

Actual behavior

The variable is undefined.

Reproducible demo

You can close the following repositories and just run yarn start.

With CRA 3:

https://github.com/guicara/create-react-app-3-bug-scss-variable-export

cra-34

With CRA 4:

https://github.com/guicara/create-react-app-4-bug-scss-variable-export

cra-4

Anyone have some ideas or suggestions?
Thank you for your help!

@guicara
Copy link
Author

guicara commented Nov 9, 2020

I've got some updates...

I have just discovered, that CRA 4 is able to read the SASS variables if the SASS file is named as <name>.module.scss.

In App.tsx of the demo repository, we can do something like that:

import colors from './template/colors.module.scss';

Not ideal (these SASS files are not CSS modules in this context) but it works.

@stale
Copy link

stale bot commented Dec 19, 2020

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.

@stale stale bot added the stale label Dec 19, 2020
@tsumo
Copy link

tsumo commented Dec 19, 2020

The issue is not resolved yet.

@stale stale bot removed the stale label Dec 19, 2020
@xmd5a
Copy link

xmd5a commented Dec 31, 2020

I've got some updates...

I have just discovered, that CRA 4 is able to read the SASS variables if the SASS file is named as <name>.module.scss.

In App.tsx of the demo repository, we can do something like that:

import colors from './template/colors.module.scss';

Not ideal (these SASS files are not CSS modules in this context) but it works.

yeah this solution works fine, but still issue is not resolved :(

@thabemmz
Copy link
Contributor

thabemmz commented Feb 5, 2021

With the new release of CRA (4.0.2), I looked into this again. Unfortunately, it is still not working.

However, after seeing this issue at css-loader, I decided to look into this again and found a more elegant solution than the one described above.

The issue is caused by the fact that in the Webpack configuration offered by Create React App. In there, the non-module scss files have the CSS-loader compileType module (that is the default). Since CSS-loader v4 broke :import and :export, you now need to explicitly specify the compileType to be icss (see webpack-contrib/css-loader#1134).

This can be configured in the css-loader options (the example is given at https://github.com/webpack-contrib/css-loader#separating-interoperable-css-only-and-css-module-features).

This means the Webpack configuration offered by Create React App needs to be modified. Since we use craco in our project, we can do the following.

In craco.config.js:

    style: {
    css: {
      loaderOptions: (cssLoaderOptions, { env, paths }) => {
        // We want to select the CSS loader config for all plain `.scss` files. In the current CRA Webpack configuration,
        // this SCSS rules are defined by using `importLoaders: 3`. To make a distinction between the rules for SCSS modules
        // and plain SCSS files, we need to look for the loaderOptions where no modules are set. The if-statement below
        // filters this and keeps existing CRA configuration for all other rules intact.
        //
        // See https://github.com/facebook/create-react-app/blob/b9963abde5870d46cd906160f98f81dbc0a5ecf2/packages/react-scripts/config/webpack.config.js#L563
        if (cssLoaderOptions.importLoaders !== 3 || cssLoaderOptions.modules) return cssLoaderOptions

        return {
          ...cssLoaderOptions,
          modules: {
            compileType: 'icss',
          },
        }
      },
    },
  },

The above configuration will make exporting SASS variables work again (without renaming files to .module.scss) 🎉.

Of course, this is very hacky and fully depends on the current setup of the CRA webpack configuration. I'll issue a PR ASAP at CRA to fix this over there.

@thabemmz
Copy link
Contributor

thabemmz commented Feb 5, 2021

PR can be found here: #10511

@guicara
Copy link
Author

guicara commented Feb 5, 2021

The above configuration will make exporting SASS variables work again (without renaming files to .module.scss)

That's great news!

Thank your for the PR @thabemmz. Hope it will be merged soon.

@william-chu
Copy link

@thabemmz Thanks for looking into this, much appreciated.

@kieranongh
Copy link

Just bumping this issue, came across it today

@richardoptibrium
Copy link

Bump

@kintz09
Copy link

kintz09 commented Mar 17, 2021

I ran into this issue today while migrating a project into a new CRA4 app. Hoping this gets fixed soon. Implementing the craco config did temporarily fit it for me.

@ianschmitz ianschmitz linked a pull request Apr 12, 2021 that will close this issue
@TakanashiOuken
Copy link

Is this fix merged in 4.0.3?

@liuliangsir
Copy link

@TakanashiOuken The issue is not resolved yet with 4.0.3

@AbhaysinghBhosale
Copy link

Getting same issues in latest version 4.0.3 and Also having vulnerabilities due to css-loader dependancies

@richardoptibrium
Copy link

richardoptibrium commented Jul 22, 2021

Bump. Please could you merge/release the fix?!

@jasperfunksmit
Copy link

The .module solution above worked for me, but in case anybody run into this issue: I could not access a sass variable in JavaScript because i exported a variable name starting with $.

Works:
:export { slideTransitionDuration: $slide_transition_duration; }

Doesn't work:
:export { $slideTransitionDuration: $slide_transition_duration; }

@GautamGupta
Copy link

GautamGupta commented Dec 14, 2021

Looks like the fix was released with CRA v5 but it didn't resolve the issue for me. I still get an error on

TS2307: Cannot find module 'styles/colors.scss' or its corresponding type declarations.
import colors from "styles/colors.scss";
                   ^^^^^^^^^^^^^^^^^^^^

@kintz09
Copy link

kintz09 commented Mar 10, 2022

Will this fix be backported as a patch in CRA4? Or will we be required to upgrade to CRA5 to resolve this issue without using CRACO?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.