"composes" not working with babel-plugin-react-css-modules - reactjs

I'm trying to use css modules in my React project. I am able to do things like:
import styles from './demo.css'
const Demo = () => <div styleName="demo">Hello</div>
And my styles are pulled from the CSS and prefixed successfully. However, when I try to use the "composes" function of CSS modules, it seems like it is completely ignored. I'm not even importing from other files - just trying to compose local classes. However, when I clone the demo project (https://github.com/gajus/babel-plugin-react-css-modules/tree/master/demo) and add a "composes" in the CSS, it works. I don't see what the difference is between my code and that in the demo...
My webpack loaders are:
loaders: [
{
test: /\.jsx?$/,
loader: 'babel?cacheDirectory',
include: PATHS.src
},
{
test: /\.css$/,
loaders: [
'style',
'css?importLoader=1&modules&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
],
include: PATHS.src,
}
]
This is my .babelrc:
{
presets: [
"es2015",
"react",
],
plugins: [
[
"react-css-modules",
{
generateScopedName: "[path]___[name]__[local]___[hash:base64:5]"
}
],
"transform-object-rest-spread",
],
env: {
development: {
presets: [
"react-hmre"
]
}
}
}

Having the same issue here. The workaround I found is by using vars instead composes.
/* colors.css */
:root {
--color: #4A90E2
}
/* button.css */
#import 'colors.css';
.button {
color: var(--blue);
}

I had this problem, and found that it was solved by adding cacheDirectory: false
For example webpack.config.js:
...
module : {
loaders : [
{
test : /\.jsx?/,
include : APP_DIR,
loader : 'babel-loader',
query: 'cacheDirectory=false',
},
...

Related

React phone number input is causing a webpack error on cypress

When i tried run a cypress test that use a react-phone-number-input a webpack error appears, this error only appears in cypress, my react project don't show this error and works fine, is there a solution in webpack or cypress that can remove this error?
Error: Webpack Compilation Error
./node_modules/react-phone-number-input/style.css 2:0
Module parse failed: Unexpected token (2:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| /* CSS variables. */
> :root {
| --PhoneInputCountrySelect-marginRight: 0.35em;
| --PhoneInputCountrySelectArrow-width: 0.3em;
# ./src/components/InputPhoneNumber/index.js 15:0-44
# ./src/components/SignUpForm/index.js
# ./src/components/ProductForm/index.js
# ./src/tests/ProductForm.spec.js
My Webpack config is this
const CopyWebpackPlugin = require('copy-webpack-plugin')
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'public' }
]
})
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader'
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader']
},
{
test: /\.s[ac]ss$/i,
use: [
{
loader: 'style-loader' // inject CSS to page
},
{
loader: 'css-loader' // translates CSS into CommonJS modules
},
{
loader: 'postcss-loader', // Run postcss actions
options: {
plugins: function () { // postcss plugins, can be exported to postcss.config.js
return [
require('autoprefixer')
]
}
}
},
{
loader: 'sass-loader' // compiles Sass to CSS
}
]
}
]
}
}
The css-loader doesn’t compile css root parameters.
This answer will help you solve the problem
https://github.com/webpack-contrib/css-loader/issues/69#issuecomment-108597013

Module parse failed: Unexpected character '#' (1:0) with Storybook 6.1.11, Webpack 5.11.0, React 17.0.1

Trying to setup a react-app with all latest versions.
Github Repo Link
Trying to run storybook with sass file imported will result in below error. Trying to run without importing the styles, storybook works.
The same code works correctly when its run as npm start run with no warnings and errors.
I have configured css modules using #dr.pogodin/babel-plugin-react-css-modules with sass, webpack 5, react 17 and with latest packages.
ERROR in ./src/assets/stylesheets/app.scss 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> #import "./base.scss";
| #import "./generics/font.scss";
| #import "./generics/spacing.scss";
# ./stories/index.js 5:0-44 8:2-10:4 8:58-10:3 9:4-49
# ./src/components/atoms/button/stories.js
babel.config.js
module.exports = {
presets: ["#babel/preset-env", "#babel/preset-react"],
plugins: [
[
"#dr.pogodin/babel-plugin-react-css-modules",
{
webpackHotModuleReloading: true,
autoResolveMultipleImports: true,
filetypes: {
".scss": {
syntax: "postcss-scss",
},
},
generateScopedName: "[name]__[local]___[hash:base64:5]",
},
],
],
};
webpack.config.js for css (partial code inlcuded)
{
test: /\.(css|sass|scss)$/,
exclude: /node_modules/,
use: [
isDev ? "style-loader" : MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: {
auto: (resourcePath) =>
resourcePath.indexOf("assets/stylesheets") === -1,
localIdentName:"[name]__[local]___[hash:base64:5]",
},
sourceMap: true,
},
},
"sass-loader",
],
}
storybook/webpack.config.js file
const custom = require('../webpack.config.js');
module.exports = {
// stories: ['../src/components/**/*.stories.js'],
webpackFinal: (config) => {
return {
...config,
module: {
rules: custom.module.rules,
},
resolve: {
...config.resolve,
...custom.resolve,
}
};
},
};
I don't know what you have done with your configuration but you would define the config things inside .storybook/main.js. And for global style css is supposed to be included in preview.js file.
In short, you have to do the few things:
Remove your .storybook/config.js and add .storybook/main.js with following content:
const custom = require('../webpack.config.js');
module.exports = {
stories: [
'../src/**/stories.js', // The name should have a prefix for component name like `button.stories.js` instead of `stories.js` like you've done. As you renamed, you can remove this pattern
"../src/**/*.stories.#(js|jsx|ts|tsx)"
],
webpackFinal: (config) => {
return {
...config,
module: {
rules: custom.module.rules,
},
resolve: {
...config.resolve,
...custom.resolve,
}
};
},
};
Create the .storybook/preview.js to import your global style:
import "../src/assets/stylesheets/app.scss";
Some people have been running into problems a some scss preset when using Storybook 6.2.0 with Webpack 5. Instead of using a preset, I recommend configuring the Webpack config in main.js as mentioned above. Here's the relevant portion of a working Storybook Webpack config for Sass:
module: {
...config.module,
rules: [
...config.module.rules,
{
test: /\.(scss)$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: function () {
return [require('precss'), require('autoprefixer')];
},
},
},
},
{
loader: require.resolve('sass-loader'),
options: {
implementation: require('sass'),
},
},
],
},
],
},
I've written more about getting Storybook off the ground with Webpack 5 (and modifying the Storybook Webpack config) over here.
Another reason this might happen: if you are adding new components to your app and the path defined for your sass-loader does not match anymore.
E.g. if you have this in your .storybook/main.js:
webpackFinal: async config => {
// Add SASS support
// https://storybook.js.org/docs/configurations/custom-webpack-config/#examples
config.module.rules.push({
test: /\.scss$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: {
compileType: "icss",
},
},
},
"sass-loader",
],
include: path.resolve(__dirname, "../"),
})
Update or completely remove the include path.

Nested classes not working in CSS Modules with webpack

Im using webpack and css-loader and style-loader to enable css modules in my React app. These are the following setup:
Webpack config:
module.exports = {
mode: "development",
entry: __dirname + "/app/index.js",
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
}
]
}
]
},
output: {
filename: "bundle.js",
path: __dirname + "/build"
},
plugins: [HTMLWebpackPluginConfig]
};
And in my React component I've coded this:
import React from "react";
import styles from "./Carousel.css";
class Carousel extends React.Component {
render() {
return (
<div className={styles["carousel"]}>
<img
className={styles["test"]}
src="https://i2.wp.com/beebom.com/wp-content/uploads/2016/01/Reverse-Image-Search-Engines-Apps-And-Its-Uses-2016.jpg?resize=640%2C426"
/>
</div>
);
}
}
export default Carousel;
In my Carousel.css file:
.carousel {
background-color: red;
.test {
width: 200px;
}
}
When I check the rendered HTML, I can see carousel class and its properties coming in the parent div. But the child img tag shows the class name but no property is associated with it.
Any idea what Im doing wrong here?
EDIT:: Sam's suggestions worked and Im summarising the changes that solved it:
Since nesting is a feature of css, we need to use sass or less. And for that I used postcss-loader.
Updated webpack config rules section:
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
},
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "css-loader",
options: {
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
}
},
*"postcss-loader"*
]
}
Also added a postcss.config.js file like this:
module.exports = {
plugins: [
require("postcss-nested")({
/* ...options */
})
]
};
And added postcss-loader, postcss-nested packages using npm install -D option.
How are you importing the css file ?
You can follow the below way to import too,
In your component,
import ‘styles.css’
In HTML element,
<div className='carousel'>
<div className='test'></div>
</div>
In webpack config,
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
}

Import Library Stylesheets With Babel-Plugin-React-Css-Modules

I am trying to include another library's css for their component in my own application. For reference, I am trying to use this data table library: https://github.com/filipdanic/spicy-datatable.
In the docs, it states Out of the box, spicy-datatable is bare-bones. Include this CSS starter file in your project to get the look from the demo. Edit it to suit your needs.
I tried to import the style sheet at the top of the component that I am building like this: import * as spicy from 'spicy-datatable/src/sample-styles.css'; in my own component file. It was not styled. I tried putting the raw code into my index.scss file in my assets/styles folder - did not work. I tried putting it in my own styles file ./component.scss - did not work.
I have them currently set up like:
import * as styles from './component.scss';
import * as spicy from 'spicy-datatable/src/sample-styles.css';
and am getting an error:
Module parse failed: Unexpected token (4:0)
You may need an appropriate loader to handle this file type.
webpack.config.js
const dirNode = 'node_modules';
const dirApp = path.join(__dirname, 'client');
const dirAssets = path.join(__dirname, 'assets');
/**
* Webpack Configuration
*/
module.exports = {
entry: {
vendor: ['lodash'],
bundle: path.join(dirApp, 'index')
},
resolve: {
modules: [dirNode, dirApp, dirAssets]
},
plugins: [],
module: {
rules: [
// BABEL
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /(node_modules)/,
options: {
compact: true
}
},
// CSS / SASS
{
test: /\.(scss)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
}
},
'sass-loader'
]
},
// IMAGES
{
test: /\.(jpe?g|png|gif)$/,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
]
}
};
.babelrc
"plugins": [
[
"react-css-modules",
{
"filetypes": {
".scss": {
"syntax": "postcss-scss"
}
},
"webpackHotModuleReloading": true
}
]
I'm not sure if I need to add something to specifically handle .css files, this is my first time working with CSS Modules. I thought react-css-modules did that so I'm not quite sure why the CSS file isn't loading correctly.
Edit:
Edited my webpack around to include CSS:
{
test: /\.(css)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
}
}
]
},
Error is gone, but styles still do not appear.
Could you try changing below:
import * as spicy from 'spicy-datatable/src/sample-styles.css';
to
import from 'spicy-datatable/src/sample-styles.css';
If you are using CSS-Modules, try below:
import spicy from 'spicy-datatable/src/sample-styles.css';
and then use the style on JSX element like below:
<h1 className={classes.<className in CSS here>}>
I setup a codesandbox with the spicy-datatable library and imported the styles and looks like it applied. The styles are in "Hello.css" file and it is imported in "index.js".
https://codesandbox.io/s/4j31xj3689
If library doesn't use css-modules (uses className attribute instead of styleName) we need to disable modules for imported css, so the class names will remain unchanged. This can be done in 2 ways:
Modify your Webpack config
module: {
rules: [
{
test: /\.(css)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: false
}
}
]
},
...
]
}
Import library css directly into your scss stylesheet (thanks to this answer pointing out how to perform proper .css import). Make sure to exclude .css file extension from import line. :global directive will prevent css-modules to modify class names for all styles within this directive.
:global {
#import "~library-module-name/.../CssFileWithoutExtension";
}

How to set root directory for webpack

I am configuring webpack for react storybook and I am having issues with the import statements paths. When I normally run my app, I have a path like this:
import { constructURLName } from "src/shared/utilities/stringManipulation";
I am using the reactQL boilerplate and it is configured so that it will return the proper module based on the src folder. How can I replicate that in storybook? Storybook currently tries to look for that stringManipulation file here:
/Users/me/development/reactQL/node_modules/src/shared/utilities/stringManipulation
So it needs to go up one directory based on my layout:
node_modules
src
pages
...
shared
utilities
stringManipulation
This is what my rule looks like for js/jsx files:
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: [
{
loader: "babel-loader",
query: {
babelrc: false,
presets: [
["env", { modules: false, exclude: ["transform-regenerator"] }],
"react"
],
plugins: [
"transform-object-rest-spread",
"syntax-dynamic-import",
"transform-regenerator",
"transform-class-properties",
"transform-decorators-legacy"
]
}
}
]
},
How can I properly set the src directory? Thanks!
You can use resolve.modules.
const path = require('path');
const config = {
...
resolve: {
modules: [
path.resolve(__dirname, 'node_modules'),
path.resolve(__dirname, './'),
]
}

Resources