Css-loader: Keep :export also for non-CSS-modules

Created on 12 Aug 2020  路  7Comments  路  Source: webpack-contrib/css-loader

  • Operating System: nix
  • Node Version: v12.17.0
  • NPM Version: 6.14.5
  • webpack Version: 4.44.1
  • css-loader Version: 4.2.1

Expected Behavior / Situation

Previously my setup was as follows

   // --------
    // SCSS GENERAL
    {
      test: /\.(scss)$/,
      exclude: /\.module\.(scss)$/,
      use: [
        // ...
        {
          loader: 'css-loader',
          options: {
            importLoaders: 3,
            sourceMap: true
          }
        },
        // ...
      ]
    },
    // --------
    // SCSS MODULES
    {
      test: /\.module\.(scss)$/,
      use: [
        // ...
        {
          loader: 'css-loader',
          options: {
            importLoaders: 3,
            sourceMap: true,
            modules: {
              mode: 'local',
              localIdentName: (development) ? '[name]__[local]--[hash:base64:5]' : '[hash:base64:16]'
            },
            localsConvention: 'asIs',
            onlyLocals: false
          }
        },
        // ...
      ]
    },

and having :export directive in non-module scss file worked

_variables.scss_

:export {
  canvasTouchPointColor: $colorSelectionText;
  canvasBackgroundColor: $colorHeaderBackground;
}

_somejavascript.js_

import styles from 'shared/scss/variables.scss';
console.log('styles.canvasTouchPointColor', styles.canvasTouchPointColor);
console.log('styles.canvasBackgroundColor', styles.canvasBackgroundColor);

Actual Behavior / Situation

Now, using the new configuration syntax

    // --------
    // SCSS GENERAL
    {
      test: /\.(scss)$/,
      exclude: /\.module\.(scss)$/,
      use: [
        // ...
        {
          loader: 'css-loader',
          options: {
            importLoaders: 3,
            sourceMap: true,
            modules: {auto: false} // unnecessary, but let us be verbose 
          }
        },
        // ...
      ]
    },
    // --------
    // SCSS MODULES
    {
      test: /\.module\.(scss)$/,
      use: [
        // ...
        {
          loader: 'css-loader',
          options: {
            importLoaders: 3,
            sourceMap: true,
            modules: {
              mode: 'local',
              localIdentName: (development) ? '[name]__[local]--[hash:base64:5]' : '[hash:base64:16]',
              exportLocalsConvention: 'asIs',
              exportOnlyLocals: false
            }
          }
        },
        // ...
      ]
    },

bringing SCSS variables into JavaScript does not work for SCSS files which are not considered modules.

Note, that moving :export to _module_ file does bring back variables into JS ->

_variables.module.scss_

@import "variables.scss";
:export {
  canvasTouchPointColor: $colorSelectionText;
  canvasBackgroundColor: $colorHeaderBackground;
}

_somejavascript.js_

import styles from 'shared/scss/variables.module.scss';
console.log('styles.canvasTouchPointColor', styles.canvasTouchPointColor);
console.log('styles.canvasBackgroundColor', styles.canvasBackgroundColor);

does work.

Modification Proposal

Is the assumption that the new implementation allows SCSS :export only to be used when modules are true?
If so can it be reverted to the previous behaviour?

Thanks!

Community help wanted 4 (important) Patch 5 (confusing) Documentation

All 7 comments

    // --------
    // SCSS GENERAL
    {
      test: /\.(scss)$/,
      exclude: /\.module\.(scss)$/,
      use: [
        // ...
        {
          loader: 'css-loader',
          options: {
            importLoaders: 3,
            sourceMap: true,
            modules: {
              compileType: 'icss'
            }
          }
        },
        // ...
      ]
    },
    // --------
    // SCSS MODULES
    {
      test: /\.module\.(scss)$/,
      // ...
    },

This setup works

Tried compileType before submitting the issue and it did not work. Was using it as shown below as I did not want modules for this loader chain

            modules: {
              compileType: 'icss'
              auto: false
            }

Apparently auto needs not to be defined. Together with the fact that previously _modules_ could be left out altogether (see OP _Expected Behavior / Situation_) the behaviour has changed quite a lot.

What about having loader behave as

            modules: {
              compileType: 'icss'
            }

if modules key is left out, instead of behaving as

            modules: undefined

as that would kind of resemble as what css-loader in practice did before v4?

There are two cases:

  • icss and modules together
  • only icss and no modules

So both configuration is valid, but maybe we should docs this

Using compileType: 'icss' is rare case, let's add docs about it

see the pull request

Using compileType: 'icss' is rare case, let's add docs about it

containing project variables in some variables.scss (and not variables.module.scss) and then @import'ing them in both component.module.scss'es as well as JavaScript files directly IMHO is not some edge case.

@evilebottnawi PR for doc addition passing now, please review. thanks!

Fixed https://github.com/webpack-contrib/css-loader/pull/1163, logic for icss and auto will be in the next major release (because it is potential breaking change), but it will be soon, because postcss@8 will be released in near future

Was this page helpful?
0 / 5 - 0 ratings

Related issues

kcjonson picture kcjonson  路  3Comments

ghost picture ghost  路  3Comments

heldrida picture heldrida  路  4Comments

jonathanong picture jonathanong  路  3Comments

cuiyue picture cuiyue  路  3Comments