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

Exporting variables from SCSS file to JavaScript no longer works in css-loader 4.x.x #1179

Closed
felipecarrillo100 opened this issue Aug 25, 2020 · 6 comments

Comments

@felipecarrillo100
Copy link

  • Operating System: Windows 10
  • Node Version: v10.17.0
  • NPM Version: 6.13.2
  • webpack Version: 4.44.1
  • css-loader Version: 4.2.1

Other:
sass-loader: "8.0.2",
style-loader: "1.2.1",

Expected Behavior

In version CSS-loader 3.x.x I was able to import SCSS variables but since I migrated to css-loader 4.x.x this no longer works, now I get an empty object.

Example:
webpack.config.js

                {
                    test: /\.(css|scss|sass)$/,
                    loader: [
                         'style-loader',
                         'css-loader',
                        'sass-loader'
                    ],
                }

_export.scss

// variables.scss
$white-color: #fcf5ed;
$dark-color: #402f2b;
$light-color: #e6d5c3;

// the :export directive is the magic sauce for webpack
:export {
  whitecolor: $white-color;
  darkcolor: $dark-color;
  lightcolor: $light-color;
}

somefile.js

const variables = require("../../../../../theme/_export.scss");
console.log(variables)

With css-loader 3.x.x and older everything works fine as expected. I get variables as an object containing the values
{
whitecolor: "#fcf5ed";
darkcolor: "#402f2b";
lightcolor: "#e6d5c3"
}

Actual Behavior

Since migrated to css-loader 4.x.x instead of the expected values I get an empty object {}
If I role back to an older version of css-loader everything works again as expected.

Code

This is a full copy of my webpack.config.js

'use strict';

const path = require('path');
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
const HtmlWebPackPlugin = require("html-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = (env, argv) => {
    const mode = argv.mode || process.env.NODE_ENV;
    console.log("Mode: " + mode);
    return {
        entry: ['./src/index.tsx'],
        output: {
            path: path.resolve(__dirname, "dist"),
            filename: 'index.js'
        },
        devtool: mode === 'production' ? undefined : "inline-source-map",
        module: {
            rules: [
                {
                    test: /\.(ts|tsx)$/,
                    enforce: 'pre',
                    exclude: /node_modules/,
                    include: /src/,         
                    use: [
                        {
                            loader: "eslint-loader",
                            options: {
                                fix: true
                            }
                        }
                    ]
                },
                {
                    test: /\.tsx?$/,
                    loader: 'ts-loader',
                    options: {
                        transpileOnly: true // IMPORTANT! use transpileOnly mode to speed-up compilation
                    }
                },
                {
                    test: /\.html$/,
                    use: [
                        {
                            loader: "html-loader",
                            options: {
                                minimize: true
                            }
                        }
                    ]
                }, {
                    test: /\.(css|scss|sass)$/,
                    loader: [
                         'style-loader',
                         'css-loader',
                        'sass-loader'
                    ],
                }, {
                    test: /\.(jpe?g|png|gif|xml|svg)$/i,
                    use: [{
                        //data-url if file size is below 5kb
                        loader: 'url-loader',
                        options: {
                            hash: 'sha512',
                            digest: 'hex',
                            name: '[hash].[ext]',
                            limit: 5000
                        }
                    }]
                }, {
                    test: /\.(woff(2)?|ttf|eot)$/,
                    use: {
                        loader: 'file-loader',
                        options: {
                            outputPath: 'fonts/'
                        }
                    }
                }]
        },
        resolve: {
            extensions: [
                '.ts',
                '.tsx',
                '.js',
                '.jsx',
                '.scss',
                '.css',
                '.svg',
                '.eof',
                '.woff',
                '.woff2',
                '.ttf',
                '.txt',
                '.xml'
            ]
        },
        plugins: [
            ...(mode === "production" ? [new MiniCssExtractPlugin({filename: "index.css"})] : []),
            new ForkTsCheckerWebpackPlugin({
                async: false
            }),
            new HtmlWebPackPlugin({
                template: "./src/index.html",
                filename: "./index.html"
            }),
            new CopyWebpackPlugin({
                patterns: [
                    {
                        from: './static',
                        globOptions: {
                            ignore: ['**/static/readme.txt']
                        }
                    }
                ]
            }),
        ],
        devServer: {
            port: 4000,
            overlay: {
                warnings: false,
                errors: true
            }
        },
        optimization: {
            minimizer: [
                new TerserPlugin({
                    terserOptions: {
                        compress: {
                            unused: false
                        }
                    }
                })
            ]
        }
    };
};

How Do We Reproduce?

Just try to export some variables in a scss files and import in a js file. It all works fine with css-loader 3.x.x or older.
With css-loader 4.x.x the imported variables are object is and empty object.

@felipecarrillo100 felipecarrillo100 changed the title Exporting variables from SCSS file to JavaScript no longer works in CSS 4.x.x Exporting variables from SCSS file to JavaScript no longer works in css-loader 4.x.x Aug 25, 2020
@alexander-akait
Copy link
Member

https://github.com/webpack-contrib/css-loader#compiletype, we even have example in docs for this case https://github.com/webpack-contrib/css-loader#separating-interoperable-css-only-and-css-module-features

@florianrubel
Copy link

Why is this issue closed? Where is the solution? I have the same problem and I can't find any solution.

@gknapp
Copy link

gknapp commented May 18, 2021

Why is this issue closed? Where is the solution? I have the same problem and I can't find any solution.

See the linked CRA 4 issue. Basically you change your css-loader options in webpack for SCSS files so the compileType is icss. Here's the change in my own config:

     test: /\.scss$/,
     use: [
-      { loader: "style-loader" },
-      { loader: "css-loader" },
+      "style-loader",
+      {
+        loader: "css-loader",
+        options: {
+          importLoaders: 1,
+          modules: {
+            compileType: "icss"
+          }
+        }
+      },

@mtolek
Copy link

mtolek commented Sep 17, 2021

I had similar issue with packages:
"css-loader": "6.2.0",
"sass-loader": "12.1.0",
"style-loader": "3.2.1",
"webpack": "5.21.0"

and configuration:
{ test: /\.scss$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'resolve-url-loader', }, { loader: 'sass-loader', options: { sourceMap: true, }, }, ], },

After upgrading style-loader from 2.0.0 to 3.2.1 SCSS variables imported in JS stops working - empty object:

`
import variables from 'shared/ReactComponents/scss/variables.scss'

export const REPORT_STATUS = {
OK: 'OK',
ERROR: 'ERROR',
NOT_TESTED: 'NOT TESTED',
}

const REPORT_STATUS_TO_COLOR_MAP = {
[REPORT_STATUS.OK]: variables.statusColorOk,
[REPORT_STATUS.ERROR]: variables.errorColor,
[REPORT_STATUS.NOT_TESTED]: variables.labelColorGray,
}
`
Finally I solved it using SCSS modules - more here:

https://github.com/webpack-contrib/css-loader#separating-interoperable-css-only-and-css-module-features

@BigglesZX
Copy link

BigglesZX commented Oct 26, 2022

I ran into (what I think is) this issue today and this thread seems to rank quite high for it so here's what ended up being my solution: make sure your JS import uses the .default property.

I had to change:

const { tabletPx } = require('../../scss/_variables.scss');

To:

const { tabletPx } = require('../../scss/_variables.scss').default;

The config for recent versions of css-loader is now:

// ...
{
    loader: 'css-loader',
    options: {
        modules: true,
    },
},
// ...

Hope this helps someone else in the same situation.

@Atozzio
Copy link

Atozzio commented Feb 23, 2023

Why is this issue closed? Where is the solution? I have the same problem and I can't find any solution.

See the linked CRA 4 issue. Basically you change your css-loader options in webpack for SCSS files so the compileType is icss. Here's the change in my own config:

     test: /\.scss$/,
     use: [
-      { loader: "style-loader" },
-      { loader: "css-loader" },
+      "style-loader",
+      {
+        loader: "css-loader",
+        options: {
+          importLoaders: 1,
+          modules: {
+            compileType: "icss"
+          }
+        }
+      },

Instead of using "compileType", the options.modules config should be mode: "icss" now according to https://github.com/webpack-contrib/css-loader#separating-interoperable-css-only-and-css-module-features

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

No branches or pull requests

7 participants