Recently I decided to build my own setup for react & webpack
So I faced some problems with UI libraries like antd or Bulma when import component like button the style of it doesn't work
this is my index.js
import React from 'react';
import ReactDom from 'react-dom';
import 'antd/dist/antd.css';
import { Button } from 'antd';
import './index.css';
const Index = () => (
<div>
<Button type="primary">Primary</Button>
</div>
)
;
ReactDom.render(<Index/>,document.getElementById('root'));
and this is my output
(I uploaded the image on imgur because I'm not allowed to upload images on StackOverflow until I got 10 reputations)
this is my webpack setting code
const path= require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports={
entry:path.resolve(__dirname,'src/index.js'),
output: {
path: path.resolve(__dirname,'dist'),
filename: "bundle.js"
},
module: {
rules: [
{
test:/\.js$/,
use:"babel-loader",
exclude:/node_modules/,
},
{
test:/\.(css|scss)$/,
use:[
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
modules: true,
camelCase: true,
localIdentName: '[local]___[hash:base64:5]',
},
},
'sass-loader',
]
},
{
test:/\.less/,
use:[
"less-loader",
]
},
{
test: /\.(gif|png|jpe?g|svg)$/i,
use: [
'file-loader',
{
loader: 'image-webpack-loader',
options: {
bypassOnDebug: true,
disable: true
}
}
]
},
{
test:/\.(jpg|png|gif)$/i,
exclude:/node_modules/,
use:{
loader: "url-loader",
options:{
limit:8000
}
}
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname,'src/index.html')
})
]
};
I ran into a similar issue, here's how I managed to solve it;
Replace your webpack rule for less files with this:
{
test: /\.less$/,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{ loader: "less-loader", options: { javascriptEnabled: true } }
]
}
NB: You should have style-loader, css-loader and less-loader installed.
Import antd.less instead of antd.css
In your index.js file, use import "antd/dist/antd.less" instead of import "antd/dist/antd.css" ensure you have less installed too.
Hope this helps!!
Related
I am trying to use CSS Modules to style my react components. I have sass-loader configured in my webpack build, however, the stylings do not get applied to my components. Please see below for a component example and my webpack config. Is there something I am doing wrong in webpack that is causing this issue or something I am doing wrong in how I am writing my component? Thanks!
sampleComponent.js:
import React from 'react';
import styles from './sampleComponent.scss';
const SampleComponent = (
<p className={styles.description}>This is some text</p>
);
export default SampleComponent;
sampleComponent.scss:
.description {
color: blue;
font-size: 20px;
}
webpack.common.js:
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const webpack = require('webpack');
const DIST_DIR = path.resolve(__dirname, "dist");
const SRC_DIR = path.resolve(__dirname, "src");
const config = {
entry: [
"babel-polyfill",
`${SRC_DIR}/app/index.js`,
`${SRC_DIR}/app/assets/stylesheets/application.scss`,
`${SRC_DIR}/app/components/index.scss`,
"font-awesome/scss/font-awesome.scss",
"react-datepicker/dist/react-datepicker.css",
"rc-time-picker/assets/index.css",
"react-circular-progressbar/dist/styles.css",
"#trendmicro/react-toggle-switch/dist/react-toggle-switch.css",
],
output: {
path: `${DIST_DIR}/app/`,
filename: "bundle.js",
publicPath: "/app/"
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
options: {
failOnWarning: false,
failOnError: true
}
},
{
test: /\.js$/,
include: SRC_DIR,
loader: 'babel-loader',
query: {
presets: ['react', 'stage-2']
}
},
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
]
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
loaders: ['file-loader?context=src/images&name=images/[path][name].[ext]', {
loader: 'image-webpack-loader',
query: {
mozjpeg: {
progressive: true,
},
gifsicle: {
interlaced: false,
},
optipng: {
optimizationLevel: 7,
},
pngquant: {
quality: '75-90',
speed: 3,
},
},
}],
exclude: path.resolve(__dirname, "node_modules"),
include: __dirname,
},
{
test: /\.woff2?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
// loader: "url?limit=10000"
use: "url-loader"
},
{
test: /\.(ttf|eot|svg)(\?[\s\S]+)?$/,
use: 'file-loader'
},
]
},
plugins: [
new MiniCssExtractPlugin({
filename: "application.css"
}),
new webpack.DefinePlugin({
'process.env.INTERNAL': JSON.stringify(process.env.INTERNAL),
}),
],
};
module.exports = config;
You could do something like
import React from 'react';
import './sampleComponent.scss';
const SampleComponent = (
<p className="description">This is some text</p>
);
export default SampleComponent;
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]'
}
}
]
}
]
}
};
I have followed instructions here to get antd working fine with CRA. But while using it from storybook, I was getting an error as:
Build fails against a mixin with message Inline JavaScript is not
enabled. Is it set in your options?
I had fixed that following suggestions on an issue I raised here.
Now, storybook understands antd but not importing components on demand. Is babel has to be configured separately for storybook?
1. On using import { Button } from "antd";
I get this:
2. On using
import Button from "antd/lib/button";
import "antd/lib/button/style";
I get:
Storybook version: "#storybook/react": "^3.4.8"
Dependency: "antd": "^3.7.3"
I have been stuck (again) with this for quite long hours googling things, any help is appreciated. Thanks!
Using Storybook 4, you can create a webpack.config.js file in the .storybook directory with the following configuration:
const path = require("path");
module.exports = {
module: {
rules: [
{
loader: 'babel-loader',
exclude: /node_modules/,
test: /\.js$/,
options: {
presets: ["#babel/react"],
plugins: [
['import', {libraryName: "antd", style: true}]
]
},
},
{
test: /\.less$/,
loaders: [
"style-loader",
"css-loader",
{
loader: "less-loader",
options: {
modifyVars: {"#primary-color": "#d8df19"},
javascriptEnabled: true
}
}
],
include: path.resolve(__dirname, "../")
}
]
}
};
Note that the above snippet includes a style overwriting of the primary button color in antd. I figured, you might want to eventually edit the default theme so you can remove that line in case you do not intend to do so.
You can now import the Button component in Storybook using:
import {Button} from "antd";
without having to also import the style file.
If you are using AntD Advanced-Guides for React and storybook v5 create .storybook/webpack.config.js with the following:
const path = require('path');
module.exports = async ({ config, mode }) => {
config.module.rules.push({
loader: 'babel-loader',
exclude: /node_modules/,
test: /\.(js|jsx)$/,
options: {
presets: ['#babel/react'],
plugins: [
['import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: true
}]
]
},
});
config.module.rules.push({
test: /\.less$/,
loaders: [
'style-loader',
'css-loader',
{
loader: 'less-loader',
options: {
modifyVars: {'#primary-color': '#f00'},
javascriptEnabled: true
}
}
],
include: [
path.resolve(__dirname, '../src'),
/[\\/]node_modules[\\/].*antd/
]
});
return config;
};
Then you can use import { Button } from 'antd' to import antd components.
I'm currently using storybook with antd and i got it to play nice, by using this config in my webpack.config.js file in the .storybook folder:
const { injectBabelPlugin } = require('react-app-rewired');
const path = require("path");
module.exports = function override(config, env) {
config = injectBabelPlugin(
['import', { libraryName: 'antd', libraryDirectory: 'es', style: 'css' }],
config,
);
config.module.rules.push({
test: /\.css$/,
loaders: ["style-loader", "css-loader", ],
include: path.resolve(__dirname, "../")
})
return config;
};
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' ]
}
I'm using and design library for my react application.
And I've faced with huge imports, that hurts my bundle (currently 1.18 mb in minified version because of ant-design lib).
var path = require('path');
var webpack = require('webpack');
var config = {
entry: {
vendor: ['react', 'react-dom','antd'],
app: './Scripts/js/app.js',
},
output: {
path: path.join(__dirname, "Scripts/bundles"),
filename: "[name].bundle.js"
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', "less-loader"]
},
{
loader: 'babel-loader',
exclude: /node_modules/,
test: /\.js$/,
options: {
presets: ['es2015', 'react', 'stage-0'],
},
},
]
},
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
new webpack.optimize.UglifyJsPlugin({ minimize: true }),
new webpack.optimize.CommonsChunkPlugin({
name: ['vendor'],
}),
new webpack.DefinePlugin({
'process.env': {
'NODE_ENV': JSON.stringify('production')
}
})
],
}
module.exports = config;
And my app
import React from 'react'
import ReactDOM from 'react-dom'
import { DatePicker } from 'antd';
ReactDOM.render(<DatePicker />, document.getElementById('container'));
Those few components are certainly not 1.2M together.
Install babel-plugin-import and add it to the babel-loader options:
options: {
presets: ['es2015', 'react', 'stage-0'],
"plugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
]
}
If you don't want to use the babel plugin, you'd have to import it this way:
import DatePicker from 'antd/lib/date-picker';
import 'antd/lib/date-picker/style/css';