Webpack 3 + Sass Loader : Cannot use scss as a module - reactjs

I'm using Webpack 3 + Sass Loader + Sass Resources Loader to build a multi theme React App.
This is my webpack.config :
{
test: /\.css$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
minimize: IS_PRODUCTION,
sourceMap: IS_DEVELOPMENT,
localIdentName: IS_DEVELOPMENT ? '[name]__[local]__[hash:8]' : '[hash:8]'
},
},
{
loader: 'postcss-loader',
options: {
sourceMap: IS_DEVELOPMENT,
plugins: postCssPlugins,
}
},
],
}),
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
sourceMap: IS_DEVELOPMENT,
}
},
{
loader: 'sass-loader',
options: {
sourceMap: IS_DEVELOPMENT
}
},
{
loader: 'sass-resources-loader',
options: {
sourceMap: IS_DEVELOPMENT,
resources: [
'./common/style/flaticon/_flaticon_class.scss',
`./common/branding/${BRANDING}/${BRANDING}.scss`,
'./common/style/bootstrap/_general_variables.scss',
'./node_modules/bootstrap/scss/bootstrap-reboot.scss', // functions, variables, mixins, reboot
'./node_modules/bootstrap/scss/_root.scss',
'./node_modules/bootstrap/scss/_type.scss',
'./node_modules/bootstrap/scss/_images.scss',
'./node_modules/bootstrap/scss/_grid.scss',
'./node_modules/bootstrap/scss/_utilities.scss',
]
},
},
]
})
},
Actually, It's working fine, but when I try to import my scss files into my react component and exploit it like a css file, the class name is undefined.
In my component file :
import styles from './ActivityGridItem.scss';
...
<div className={`m-2 ${styles.activityTypeIcon}`}></div>
Normally, the style .activityTypeIcon should be applied to my div, but right now it's undefined.
I try to add the options "modules: true" like this :
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
use: [
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: IS_DEVELOPMENT,
}
},
But then, every sass files are recognized as a module and I cannot use the global boostrap class, as row, col, m-*, etc.

There's a couple of ways to do it
You can use global block in css-modules to make bootstrap classes global.
You can create 2 loaders, one with css-modules enabled and another with global styles and differentiate them somehow. For example, you might make all files that end with .module.scss use modules: true.

Related

ReactJS custom webpack config, trying to hash css class names while using both css-loader and sass-loader

My .css or .scss files won't load at all.
What I'm trying to achieve is to hash my class names using css-loader option localIdentName.
I'm working on ReactJS with custom webpack config. This is one of my rules inside webpack.config.js:
{
test: /(\.css|\.scss|\.sass)$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
options: {
modules: {
localIdentName: "[path][name]__[local]--[hash:base64:5]",
}
},
},
{
loader: 'sass-loader',
options: {
},
},
],
},

Is there a way to limit classname length with NPM CSS Loader/Style Loader in react?

I configured on my React webpack CSS Loader and Style Loader to obfuscate classNames when a CSS module is loaded.
Although the generated obfuscated className seems too long, I'd like to know if there is a parameter or something I can change on my configuration (webpack) to limit the className size.
ClassName example: _2BzySvHGRXbDRB3RRdNEOO
Webpack code:
{
test: /\.css$/,
use: [
{
loader: 'style-loader'
},
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: 1,
localsConvention: 'dashes'
}
}
]
}
You can use localIdentName to manipulate the CSS fields.
e.g.
{
test: /\.css$/i,
loader: 'css-loader',
options: {
modules: {
mode: 'local',
exportGlobals: true,
localIdentName: '[path][name]__[local]--[hash:base64:5]',
context: path.resolve(__dirname, 'src'),
hashPrefix: 'my-custom-hash',
},
},
},
This may not work depending on your webpack version:
What worked for the user:
ref:https://github.com/rails/webpacker/issues/2197
{ test: /\.css$/,
use: [
{ loader: 'style-loader' },
{ loader: 'css-loader',
options: {
modules: true,
importLoaders: 2,
localsConvention: 'dashes',
modules: { localIdentName: '[hash:base64:5]',
},
}
}
]
},
if you remove the hash from the end, or just use the hash, you'll significantly reduce the class name length. or you can write a custom function in its place to reduce it.
ref: https://github.com/webpack-contrib/css-loader#localidentname
ref: Modify output of localIdentName / getLocalIdent

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

Error loading less module in react

When I try to import a .less from my React component I get the following error:
Module not found: '[object Object]' in /path/to/src
Here's a part of my webpack config that's taking care of css and less loading:
...
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: true,
importLoaders: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
'postcss-loader'
]
})
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
importLoaders: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
'less-loader'
]
})
},
...
In my component, I'm importing the .less style file, like so:
import styles from './App.less'
I've tried reading related github issues and been debugging this for a while. Would love some help!

Using Webpack with SASS and PostCSS in Angular2

Init
Im trying to use webpack with the sass-loader and the postcss-loader. I already tried different solutions but nothing worked like I want it to.
I tried the solution from Angular 2 Starter Pack with the raw-loader and the sass-loader, but than the postcss-loader didnt work.
Code
Angular 2 Component
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
// styles: [
// require('./app.component.scss')
// ]
})
Webpack module loader
{
test: /\.scss$/,
loaders: ['to-string-loader', 'css-loader', 'postcss-loader', 'resolve-url-loader', 'sass-loader']
}
Problem
With these code lines everything works but the styles are added in the <head> tag within the <style> tag. At some point I would have hundreds of style lines which I want to avoid.
If I change my loader code to this:
loader: ExtractTextPlugin.extract('to-string-loader', 'css-loader', 'postcss-loader', 'resolve-url-loader', 'sass-loader?sourceMap')
and add this to the webpack config
plugins: [
new ExtractTextPlugin('style.css')
]
it results in an error
Uncaught Error: Expected 'styles' to be an array of strings.
The style.css is actually linked in the html code.
Im searching for a solution which allows me to use sass, postcss and a single .css file.
I just ran into this issue and figured out a solution. I'm pretty sure its the "to-string-loader". The dev config below is working for me using Webpack 4 and Angular 7. It allows a global stylesheet (Tailwind CSS in my case) alongside component styles. Hot module replacement is also working for editing both entries.
entry: {
app: './src/main',
styles: './src/assets/styles/styles'
},
resolve: {
extensions: ['.ts', '.tsx', '.mjs', '.js', '.scss'],
},
module: {
rules: [
{
// Process the component styles
exclude: path.resolve(__dirname, 'src/assets/styles/styles'),
test: /\.(scss)$/,
use: [
{ loader: 'raw-loader' }, // Load component css as raw strings
{
loader: 'postcss-loader', // Process Tailwind CSS
options: {
sourceMap: 'inline',
}
},
{
loader: 'sass-loader', // Compiles Sass to CSS
},
]
},
{
// Process the global tailwind styles
include: path.resolve(__dirname, 'src/assets/styles/styles'),
test: /\.(scss)$/,
use: [
{
loader: 'style-loader', // Allow for HMR
},
{
loader: 'postcss-loader', // Process Tailwind CSS
options: {
sourceMap: 'inline',
}
},
{
loader: 'sass-loader', // Compiles Sass to CSS
},
]
},
]
},
The style-loader will extract the styles into the head at runtime, and allow for HMR. In your prod config, you can use css-loader alongside MiniCssExtractPlugin to extract and inject the global styles as a .css file into the head:
{
// Process the global tailwind styles
include: path.resolve(__dirname, 'src/assets/styles/styles'),
test: /\.(scss)$/,
use: [
{ loader: MiniCssExtractPlugin.loader },
{ loader: 'css-loader' },
{
loader: 'postcss-loader', // Process Tailwind CSS
options: {
sourceMap: false,
}
},
{
loader: 'sass-loader', // Compiles Sass to CSS
},
]
},

Resources