tailwind css with css modules in next.js - reactjs

How to config next.js to support Simultaneous tailwind css with css modules?
I want tailwindcss wrap whole project:
// /tailwind.scss
:global {
#import "tailwindcss/base";
#import "tailwindcss/components";
#import "tailwindcss/utilities";
}
// /test-module.css
.example {
font-size: 36px;
}
// /pages/_app.jsx
import '../talwind.scss';
...
And in a sample component:
// /components/my-component.jsx
import css from '../test-module.css';
const Test = () => (
<div className={`bg-red-500` ${css.example}}>Test Tailwind with CSS</div>
);

A solution is split webpack style loader. A loader for global css another for css modules loader so webpack loader is looks like below:
{
test: /\.s?[ac]ss$/,
exclude: /\.global.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: !isProduction,
reloadAll: true,
},
},
// 'css-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: {
localIdentName: '[name]__[local]___[hash:base64:5]',
},
},
},
'postcss-loader',
{ loader: 'sass-loader', options: { sourceMap: true } },
],
},
{
test: /\.global.css$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: !isProduction,
reloadAll: true,
},
},
'css-loader',
'postcss-loader',
],
},

I had the same problem, I did the following and it worked:
const Test = () => (
<div className={["bg-red-500", css.example].join(" ")}>
Test Tailwind with CSS
</div>
);

You need to write classname like this
const App = () => {
<h1 className={[style[`bg-teal-600`], style.holi].join(' ')}>Holi</h1>;
};

Related

Add wrapper class to less files using webpack

I am using webpack v5.74.0.
I want to add a custom class to all CSS rules at build time using webpack. Example for reference
.input-text {color: red}
should become
.container .input-text {color: red}
Custom wrapper class needs to be added inside less files. Not able to find any loader in webpack to prefix this container class.
Please suggest.
try the below code in your webpack config to add a wrapper class for all classes present in your project.
module: {
rules: [
{
test: /\.(css|less)$/i,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
},
{
loader: "postcss-loader",
options: {
postcssOptions: {
plugins: {
"postcss-increase-specificity": {
stackableRoot: `.container`,
repeat: 1,
},
},
},
},
},
{
loader: "less-loader",
options: {
lessOptions: {
javascriptEnabled: true,
},
},
},
],
},
],
}

Obfuscate React classNames in existing codebase

Hi guys
I am working on a big React application with an existing code-base (100+ components). Currently, we are using the traditional styling method, example:
JSX:
<div className="div" />
SCSS:
.div {
/* ... */
}
We are using webpack with these loaders:
/* ... */
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: '../'
}
},
'css-loader',
'postcss-loader',
{
loader: 'sass-loader',
options: { implementation: sass }
}
]
/* ... */
Is there any way to obfuscate these classNames from both JSX and SCSS without rewriting the whole thing? Is it also possible to rewrite only some components to be obfuscated or do we have to rewrite it all?
Thanks.
css-loader has a modules option which when set to true obfuscates class names. Unfortunately, this will obfuscate all of the class names and will require you to change all usages of <div className="div" /> to:
import styles from <stylesheet>;
<div className={styles.div} />
Edit:
The only way I can think of avoiding having to change all of the usages at once is by splitting your css config in webpack with two patterns, for example:
{
test: /.*dirA\/.*\.css/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true } }, ...]
},
{
test: /.*dirB\/.*\.css/,
use: [{ loader: 'style-loader' }, { loader: 'css-loader' }, ...]
}
Solution for ejected Create-react-app
Example classNames: a_a, a_b, a_c .... etc.
Eject app
Install incstr
Create getScopedName.js at the config folder.
const incstr = require('incstr');
const createUniqueIdGenerator = () => {
const uniqIds = {};
const generateNextId = incstr.idGenerator({
alphabet: 'abcefghijklmnopqrstuvwxyzABCEFGHJKLMNOPQRSTUVWXYZ',
});
return (name) => {
if (!uniqIds[name]) {
uniqIds[name] = generateNextId();
}
return uniqIds[name];
};
};
const localNameIdGenerator = createUniqueIdGenerator();
const componentNameIdGenerator = createUniqueIdGenerator();
module.exports = (localName, resourcePath) => {
const componentName = resourcePath
.split('/')
.slice(-2, -1)[0];
const localId = localNameIdGenerator(localName);
const componentId = componentNameIdGenerator(componentName);
return `${componentId}_${localId}`;
};
Now...
Open the webpack.config.js and add:
const getScopedName = require('./getScopedName')
Find the ~445-460 rows and replace with:
{
test: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
sourceMap: isEnvProduction && shouldUseSourceMap,
modules: {
...(isEnvDevelopment ? {
localIdentName: '[path]_[name]_[local]',
} : {
getLocalIdent: (context, localIdentName, localName) => (
getScopedName(localName, context.resourcePath)
),
})
},
}),
}
It's all. :)

Make named import of Sass file available as a string

I'm building a web component in React and need to pass my compiled component styles, which are written in Sass, into the the component's <style> tag as a string.
Component code:
<MyWebComponent> is already successfully set up to make the component's shadow using ReactShadow
It's currently working if I use a compiled CSS file using this import statement:
import componentCSS from '!!css-loader!./my-component/index.css';
I need:
to use an SCSS file in that import
to do away with the inline !!css-loader! loader config syntax in the component code
import componentCSS from './my-component/index.scss';
...
render() {
return (
<MyWebComponent shadowStyles={[componentCSS]}> // componentCSS needs to be a string
<h1>Hello Web Component</h1>
</MyWebComponent>
);
}
If I console.log(componentCSS), I get an empty object {}.
the style bits of Webpack config:
...
{
test: /\.scss$/,
include: [
path.resolve(__dirname, './web-components'),
],
use: [
'style-loader',
{
loader: 'css-loader',
options: { importLoaders: 1 }
},
{
loader: 'postcss-loader',
options: { sourceMap: true }
},
{
loader: 'resolve-url-loader',
options: { sourceMap: true }
},
{
loader: 'sass-loader',
options: { sourceMap: true, outputStyle: 'compressed' }
},
{
loader: '#epegzz/sass-vars-loader',
options: {
syntax: 'scss',
files: [path.resolve(__dirname, './scss/index.scss')]
}
}
]
},
{
test: /\.css$/,
include: path.resolve(__dirname, './web-components'),
use: [
'raw-loader'
]
},
...
I've explored making a custom loader to no success, like trying to replace the import string in the component code with the working inline loader syntax:
// my-loader.js / Custom webpack loader
module.exports = function(content) {
content = content.replace(
"import componentCSS from './my-component/index.scss'",
`import componentCSS from '#epegzz/sass-vars-loader?syntax=scss&files[]=${path.resolve(__dirname, './scss/index.scss')}!sass-loader!css-loader!./my-component/index.scss'`
)
return content;
};
Before I go too far down the custom loader rabbit hole, is there a config option or syntax change that is possible to make it work?

How to connect styles from the npm library to a project where css-modules are used?

For the project I use the React-Quill package https://github.com/zenoamaro/react-quill, it is indicated that you can import import 'react-quill / dist / quill.snow.css' styles.
Such import into the project component does not include styles, since the project uses css-modules. How to import styles in this case?
webpack config
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
module: true,
importLoaders: 1,
localIdentName: '[path][name]__[local]'
}
},
{
loader: 'postcss-loader'
}
]
},
You can use a resourceQuery so you are able to load regular global CSS as well as CSS modules.
Example
module.exports = {
//...
module: {
rules: [
{
test: /.css$/,
oneOf: [
{
// import 'react-quill/dist/quill.snow.css?global'
resourceQuery: /global/,
use: ['style-loader', 'css-loader', 'postcss-loader']
},
{
use: ['style-loader', 'css-loader', 'postcss-loader'],
options: {
modules: true,
localIdentName: '[name]__[local]_[hash:base64:5]'
}
}
]
}
]
}
};

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' ]
}

Resources