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

modules.auto=true ignores module.css!=!./some-file #1381

Closed
jantimon opened this issue Sep 30, 2021 · 17 comments
Closed

modules.auto=true ignores module.css!=!./some-file #1381

jantimon opened this issue Sep 30, 2021 · 17 comments

Comments

@jantimon
Copy link

jantimon commented Sep 30, 2021

Bug report

The css-loader option module: { auto: true } provides a great default for mixing css files and css modules.
Many webpack abstractions like cra or nextjs make use of it.

Lets say we have the following css-loader configuration:

{
  test: /\.css$/,
  use: [
    MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        modules: {
            auto: true,
            exportNamed: true
        }
    }
  }]
}

It works if the real file is called ./demo.module.css

import { myClass } from './demo.module.css';

However if there is only a synthetic css file e.g. if a .js file contains the css it works only partially.
Webpack uses the correct loader however the css-loader does not identify the file as a .module.css file:

import { myClass } from './demo.module.css!=!./file.js';

Actual Behavior

The css-loader acts the very same way as if css modules would be disabled

Expected Behavior

The css-loader should identify synthetic file names in auto mode

How Do We Reproduce?

{
  test: /\.css$/,
  use: [
    MiniCssExtractPlugin.loader,
    {
      loader: 'css-loader',
      options: {
        modules: {
            auto: true,
            exportNamed: true
        }
    }
  }]
}

index.js

import { myClass } from './demo.module.css!=!./file.js';
console.log(myClass);

file.js

.myClass { color: orange }

Please paste the results of npx webpack-cli info here, and mention other relevant information

System:
    OS: macOS 11.4
    CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
    Memory: 3.20 GB / 16.00 GB
  Binaries:
    Node: 15.12.0 - ~/.nvs/default/bin/node
    Yarn: 1.22.10 - ~/.nvs/default/bin/yarn
    npm: 7.6.3 - ~/.nvs/default/bin/npm
  Browsers:
    Brave Browser: 94.1.30.86
    Chrome: 94.0.4606.61
    Chrome Canary: 96.0.4658.0
    Edge: 94.0.992.31
    Firefox: 90.0
    Firefox Developer Edition: 92.0
    Safari: 14.1.1
    Safari Technology Preview: 15.0
  Packages:
    webpack: ^5.55.1 => 5.55.1 
    webpack-cli: ^4.8.0 => 4.8.0 

If you think this should be fixed I can work on a PR if you like

@alexander-akait
Copy link
Member

You can do - import { myClass } from './demo.module.css!=!./file.modules.js';

@alexander-akait
Copy link
Member

hm, also we already support it https://github.com/webpack-contrib/css-loader/blob/master/src/utils.js#L523, check your css-loader version

@alexander-akait
Copy link
Member

In future we will drop it, because it is wrong, I recommend to use #1381 (comment)

@jantimon
Copy link
Author

jantimon commented Oct 1, 2021

Hey Alex :)

thanks for your quick response!

Unfortunately it is not working with css-loader 6.3.0 (latest).

Here is a full (but minimal) reproduction example which is not working:
css-loader-issues-1381.zip

If you remove auto:true from the webpack.config.js it works otherwise the import fails.

I also checked https://github.com/webpack-contrib/css-loader/blob/master/src/utils.js#L523 and matchResource is undefined. Could this be a webpack bug?

@alexander-akait
Copy link
Member

Here is a full (but minimal) reproduction example which is not working:
reproduction.zip

I can't open your archive, can you use github and create repo?

Could this be a webpack bug?

No

@jantimon
Copy link
Author

jantimon commented Oct 1, 2021

Oh sorry.. sure here is the repo https://github.com/jantimon/css-loader-issue-1381

I also checked in the dist file so you can see that there are no class names exported:
https://github.com/jantimon/css-loader-issue-1381/blob/b80f2b3cf3c869b26a5ee0f18e58f702a4fb5bdb/dist/main.js#L5-L16

to see the expected result deleting the following line:
https://github.com/jantimon/css-loader-issue-1381/blob/b80f2b3cf3c869b26a5ee0f18e58f702a4fb5bdb/webpack.config.js#L20

@jantimon
Copy link
Author

jantimon commented Oct 1, 2021

@alexander-akait could you please reopen the issue?

@alexander-akait
Copy link
Member

I will look at this in near future and describe why it will not work

@alexander-akait
Copy link
Member

mini-css-extract-plugin uses pitch phase, so request is modified and matchResource doesn't exist anymore, you should use:

import { demo } from './styles.module.css!=!./colors.modules.txt'

again !=! is special syntax, I recommend to migrate on query, i.e. import { demo } from './colors.modules.txt?cssModules'

@jantimon
Copy link
Author

jantimon commented Oct 1, 2021

hey alex

thank you so much for your patience and time :) I am asking those questions to improve an open source plugin (linaria) with webpacks new importModule loader api.. so I won't make any money out of it but still I would like to send you a small present from switzerland.. if you like sweets let me know your address (send me an email) and I'll send sth small

Linaria is a plugin which already works well with existing webpack configs like nextjs so I would rather prefer not to introduce a query with custom extract css and css-loader configuration on top

I'll need to take a closer look and will create a bug for the extract css plugin loader if it makes sense.. in the end it would be cool if it works the same way for style-loader and extract css plugin - what do you think?

thanks already for pointing me to the right direction :)

@alexander-akait
Copy link
Member

@jantimon Why do you use this syntax? Can you provide more context? Why it is JS file? Do you extract CSS from JS file?

@jantimon
Copy link
Author

jantimon commented Oct 2, 2021

exactly - in short (very basic example):

const Button = styled.div`
  color: red
`

is converted twice with two outputs:

  1. javascript without css (but only the css class name)
  2. css module

however there is more - it maps runtime code to css-variables and has improved tree shaking for js code which runs only at build time

if you like to see it in action I can prepare a codesandbox for you

@alexander-akait
Copy link
Member

So you want to extract CSS from JS file and when bundle it using mini-css-extract-plugin, i.e.:

.random-generated-class-name {
  color: red
}

and you don't want to rename JS file on file.modules.js?

@jantimon
Copy link
Author

jantimon commented Oct 2, 2021

that's correct :)

I would like to do the following transform (simplified):

file1.js

export const Button = styled.button`color:orange`;

to:

import { buttonClass } from './file1.module.css!=!./file1.js'
export const Button = (content) => `<button class="${buttonClass}">${content}</button>`

@jantimon
Copy link
Author

jantimon commented Oct 2, 2021

in the meantime I found a hack to not use !=! - I guess it will break sourcemaps but at least the compilation result is correct

file1.js

export const Button = styled.button`color:orange`;

to:

import { buttonClass } from 'my-lib/placeholder.module.css?extractFrom=/absolute/path/to/file1.js'
export const Button = (content) => `<button class="${buttonClass}">${content}</button>`

that way I can reuse all existing .module.css loader settings

@jantimon
Copy link
Author

jantimon commented Oct 3, 2021

here is the result of a poc with the hack described above:
index_js_—_linaria-poc

@alexander-akait
Copy link
Member

@jantimon let's open an issue in webpack, because I can't control it in css-loader/style-loader/mini-css-extract-plugin, we jsut ream property from loaderContext, but webpack don't set it

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

2 participants