Webpack not picking up changess to scss - reactjs

Here are my files... webpack compiles fine but not picking up style changes. I have followed 2 tutorials and just want to get styling working with webpack under a basic development built process.
webpack.config.js:
var webpack = require('webpack')
var path = require('path')
var BUILD_DIR = path.resolve(__dirname + '/build')
var APP_DIR = path.resolve(__dirname + '/app')
var config = {
entry: APP_DIR + '/index.jsx'
, output: {
path: BUILD_DIR
, filename: 'bundle.js'
, publicPath: '/'
}
, resolve: {
extensions: ['.js', '.jsx']
}
, devtool: 'source-map'
, devServer: {
inline: true
, contentBase: BUILD_DIR
, port: 3333
}
, module: {
rules: [
{
test: /\.jsx?/
, include: APP_DIR
, loader: 'babel-loader'
, query: {
presets: ['es2015', 'stage-0', 'react']
}
},
{
test: /\.scss$/,
use: [//{
// loader: "style-loader" // creates style nodes from JS strings
//}, {
{ loader: "css-loader" // translates CSS into CommonJS
}, {
loader: "sass-loader" // compiles Sass to CSS
}]
}
]
}
}
module.exports = config
index.jsx
import React, { Component } from 'react'
import ReactDOM from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import reducer from './reducers/index.js'
require('./stylesheets/main.scss');
// Create a store
let store = createStore(reducer);
import App from './components/App.jsx'
ReactDOM.render(
<Provider store={store}>
<App />
</Provider> , document.getElementById('app'));
main.scss:
.app {
#import 'components/all';
}
components/all:
#import 'product';
_product.scss
.pr-product {
width: percentage(1/7);
float: left;
text-align: center;
padding: 0.5rem;
font-size:2rem;
font-weight: 400;
border-radius: 0.25rem;
transition: background-color 0.25s ease-in-out;
color: pink;
background-color: orange;
// Variants
&.past, &.future {
opacity: 0.5;
}
// States
&:hover {
cursor: pointer;
background-color: rgba(orange, 0.3);
}
}
product.jsx:
import React from 'react'
let Product = ({id, name, cost, handleClick}) => (
<div className='pr-product'>
{name} ${cost} <button onClick={() => handleClick(id)}>Add to cart</button>
</div>
)
export default Product
index.html:
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<!-- Made no difference: <link rel="stylesheet" href='../app/stylesheets/main.scss'> -->
</head>
<body>
<div id='app' class='app'></div>
<script src='bundle.js'></script>
</body>
</html>
Thank you if you can help. . .
EDIT:
I've incorporated all of the below recommendations and still no luck getting webpack to pick up css. Here is my modified webpack config:
var webpack = require('webpack')
var path = require('path')
var BUILD_DIR = path.resolve(__dirname + '/build')
var APP_DIR = path.resolve(__dirname + '/app')
var CSS_DIR = path.resolve(__dirname + '/app/stylesheets')
var config = {
entry: APP_DIR + '/index.jsx'
, output: {
path: BUILD_DIR
, filename: 'bundle.js'
, publicPath: '/'
}
, resolve: {
extensions: ['.js', '.jsx', '.scss']
}
, devtool: 'source-map'
, devServer: {
inline: true
, contentBase: BUILD_DIR
, port: 3333
}
, module: {
rules: [
{
test: /\.jsx?/
, include: APP_DIR
, loader: 'babel-loader'
, query: {
presets: ['es2015', 'stage-0', 'react']
}
},
{
test: /(\.scss)$/,
include: CSS_DIR,
use: [{loader: 'css-hot-loader'},
{loader: "style-loader" }, // creates style nodes from JS strings
{loader: "css-loader"}, // translates CSS into CommonJS
{loader: "sass-loader?" + JSON.stringify({ includePaths: [ CSS_DIR ], sourceMap : true })} // compiles Sass to CSS
]
}
]
}
}
module.exports = config

Try to make use of css-hot-loader
{
test: /(\.scss)$/,
use: [{loader: 'css-hot-loader'},
{loader: "style-loader"}, // creates style nodes from JS strings
{loader: "css-loader"}, // translates CSS into CommonJS
{loader: "sass-loader"} // compiles Sass to CSS
]
},

Related

React-Hot-Loader Not Preserving State. v.4.12.21

I followed steps from given https://www.npmjs.com/package/react-hot-loader
Install
npm install react-hot-loader
Add react-hot-loader/babel to your .babelrc:
//.babelrc
{
"plugins": ["react-hot-loader/babel"]
}
Mark your root component as hot-exported:
//Button.js
class Button extends React.Component {
constructor(props) {
super(props);
this.state = {
counter: 1,
};
}
handleClick = () =>
this.setState({
counter: this.state.counter + 1,
});
render() {
return (
<div>
<h2> Cool Counter {this.state.counter} !!!!</h2>
<button onClick={this.handleClick}>{this.state.counter}</button>
</div>
);
}
}
export default hot(Button);
//App.js
import React from 'react';
import { hot } from 'react-hot-loader/root';
import Button from './controls/Button';
const App = () => (
<div style={{ color: 'purple' }}>
<Button />
</div>
);
export default hot(App);
Make sure react-hot-loader is required before react and react-dom:
//Main.js
import 'react-hot-loader';
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App';
import './main.scss';
ReactDOM.render(<App />, document.getElementById('container'));
If you need hooks support, use #hot-loader/react-dom
npm install #hot-loader/react-dom
Use webpack aliases
// webpack.config.js
module.exports = {
// ...
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom',
},
},
};
//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>React-Hot-Loader-Test</title>
</head>
<body>
<div id="container"></div>
<script src="/public/main.js"></script>
<link href="/public/main.css" rel="stylesheet" />
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
</body>
//server.js
var webpack = require('webpack');
var WebPackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
new WebPackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
}).listen(8080, 'localhost', function (err, result) {
if (err) {
return console.log(err);
}
console.log('Listening on localhost:8080');
});
//webpack.config.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
entry: {
main: ['react-hot-loader/patch', './src/main.js'],
},
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom',
},
modules: [path.resolve('./src'), path.resolve('./node_modules')],
},
output: {
path: path.resolve(__dirname, 'public'),
filename: devMode ? '[name].js' : '[name].[chunkhash].js',
publicPath: '/public/',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['react-hot-loader/webpack', 'babel-loader'],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'sass-loader',
],
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? '[name].css' : 's[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
}),
],
};
//.babelrc
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
"plugins": ["#babel/plugin-proposal-class-properties", "react-hot-loader/babel"]
}
Finally running 2 command
1. webpack -d
2. node server.js
result:
λ node server up and running
i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /public/
i 「wds」: Content not from webpack is served from G:\Projects\React-Second
i 「wds」: 404s will fallback to /index.html
react hot loading only working for html,css,jsx change
Question:
Hooks not storing previous state upon cliking button and then changing any css,html or jsx, UseState or Set state not preserving the state, it always starts with 1.
Please help what did i miss, i'am struggling from hours.
Regards
Shaz
Found the solution
//webpack.config.js
const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const devMode = process.env.NODE_ENV !== 'production';
module.exports = {
mode: 'development',
devtool: 'inline-source-map',
entry: {
main: ['webpack-dev-server/client?http://localhost:8080', 'webpack/hot/only-dev-server', './src/main.js'],
// main: ['react-hot-loader/patch', './src/main.js'],
},
resolve: {
alias: {
'react-dom': '#hot-loader/react-dom',
},
modules: [path.resolve('./src'), path.resolve('./node_modules')],
},
output: {
path: path.resolve(__dirname, 'public'),
filename: devMode ? '[name].js' : '[name].[chunkhash].js',
publicPath: '/public/',
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
// use: {
// loader: 'babel-loader',
// // options: {
// // presets: ['#babel/preset-env', '#babel/preset-react'],
// // },
// },
use: ['react-hot-loader/webpack', 'babel-loader'],
//use: ['babel-loader'],
},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
},
'css-loader',
'sass-loader',
],
},
],
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: devMode ? '[name].css' : 's[name].[hash].css',
chunkFilename: devMode ? '[id].css' : '[id].[hash].css',
}),
],
// devServer: {
// contentBase: path.join(__dirname),
// compress: false,
// port: 8080,
// historyApiFallback: true,
// watchContentBase: false,
// publicPath: '/public/',
// },
};

LESS style not applied to react component in react+webpack application

In a react + web pack application, I'm trying to style my react component using LESS, but the style does not get applied, although I get no errors, so I wouldn't know where to look. Of course, my devDependencies includes less, less-loader, CSS-loader and style-loader.
webpack.config.js
const path = require("path");
const webpack = require("webpack");
module.exports = {
entry: './src/index.js',
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: [
"babel-loader",
"eslint-loader"
]
},
{
test: /\.(c|le)ss$/,
use: [
"style-loader",
"css-loader",
"less-loader",
]
}
]
},
resolve: {
extensions: [".js", ".jsx"],
alias: {
"#components": path.resolve(__dirname, "src/components"),
"#containers": path.resolve(__dirname, "src/containers")
}
},
output: {
path: __dirname + '/dist',
filename: 'bundle.js'
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
hot: true
}
};
components/App/App.jsx
import React from "react";
import Body from "#components/Body/Body.jsx";
import Footer from "#components/Footer/Footer.jsx";
import styles from "./App.less";
class App extends React.Component {
render() {
return <div className={styles.root}>
<h1> test </h1>
<Body />
<Footer />
</div>;
}
}
export default App;
components/App/App.less
.root {
width: 100%;
height: 100%;
background-color: coral;
h1 {
margin-top: 200px;
color: red;
}
}
I expected to see the style applied, but it's not.
Try setting "root" as string-value to className.
The way your webpack has been configured, the content of the LESS-files will not be exported as css-rules but only collected to be rendered into a style-tag.
You need to import the less-file, so webpack knows which files to consider, but you neither can access its rules, or its styles. So to make it work, you simply set the CSS-class names so that the compiled CSS-rules match.
I had to enable CSS Modules in the Webpack config:
{
test: /\.(c|le)ss$/,
use: [
"style-loader",
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: "[path][name]__[local]--[hash:base64:5]",
},
},
"less-loader"
]
},

How do you remove unused classes with Webpack 4 tree shaking with CSS modules?

Someone made a great example to remove unused CSS based on whether or not the JS Module is used, but I am trying to figure out how to remove the unused CSS classes from the bundle that are not actually used by components.
Example
// Sub.scss
.sub-container {
background-color: green;
}
.unused-junk {
color: blue;
}
// Sub.js
import React from "react";
import styles from "./Sub.scss";
export default function Sub() {
return <div className={styles.subContainer}>Hi from sub.</div>;
}
// App.scss
.app-container {
background-color: red;
}
// App.js
import React from "react";
import ReactDOM from "react-dom";
import Sub from "./Sub";
import styles from "./App.scss";
function App() {
return (
<div className={styles.appContainer}>
Hi from app.
<Sub />
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
entry: "./src/App.js",
output: {
path: __dirname + "/build",
filename: "bundle.js"
},
module: {
rules: [
{
test: /\.js/,
loader: "babel-loader",
include: __dirname + "/src",
query: {
presets: ["react"]
}
},
{
test: /\.scss/,
use: [
MiniCssExtractPlugin.loader,
{
loader: "css-loader",
options: {
modules: true,
camelCase: true,
importLoaders: 1,
localIdentName: "[name]--[local]--[hash:base64:5]"
}
},
"sass-loader"
],
include: __dirname + "/src"
}
]
},
plugins: [
new CopyWebpackPlugin([{ from: `src/index.html`, to: "index.html" }]),
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
};
// CSS bundle
.App--app-container--3wd6W {
background-color: red; }
.Sub--sub-container--38uqh {
background-color: green; }
.Sub--unused-junk--2-h5r {
color: blue; }
Is there a way to tree shake the .unused-junk class from the bundle?

SCSS file cannot import node_module

Tried #import "~react-icons" in an SCSS file.
I get an error: Module build failed:
#import "~react-icons";
^
File to import not found or unreadable: ~react-icons.
This was an npm module that I installed and is on package-json.
My scss code looks like this, the error is at the first line:
#import "~react-icons";
input {
width: 100%;
box-sizing: border-box;
border: 2px solid #ccc;
border-radius: 4px;
font-size: 16px;
background-color: white;
padding: 12px 20px 12px 20px;
margin-bottom: 20px;
}
My webpack configuration looks like this:
const webpack = require('webpack');
const path = require('path');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
let BUILD_DIR = path.resolve(__dirname, 'dist');
let APP_DIR = path.resolve(__dirname, 'src');
let config = {
entry: path.join(APP_DIR, '/index.js'),
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.jsx?/,
include: APP_DIR,
loaders: ['babel-loader']
},
{
test: /\.scss$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: ['css-loader', 'sass-loader'],
publicPath: "/dist"
})
},
{
test: /\.(ttf|eot|svg|gif|woff(2)?)(\?[a-z0-9]+)?(\?v=
[0-9]\.[0-9]\.[0-9])?$/,
loader: 'file-loader',
}
]
},
resolve: {
extensions: ['.js', '.jsx']
},
devServer: {
contentBase: path.join(__dirname),
// serve index.html in place of 404 responses to allow HTML5
// history
historyApiFallback: true
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
title: 'Project',
minify: {
collapseWhitespace: true
},
hash: true,
template: './index.html'
}),
new ExtractTextPlugin({
filename: 'style.css',
disable: false,
allChunks: true
})
]
};
module.exports = config;
There is not an scss file to import for react-icons. You have to import the icons in the file you want to use:
import FaSearch from 'react-icons/lib/fa/search';
class Search extends React.Component {
render() {
return <FaSearch />
}
}

How to fix: Uncaught Error: _registerComponent(...): Target container is not a DOM element

When I compile and run my Webpack application, I keep getting thrown this error. Anyone have an idea what my be causing it. I have tried adding the <div id="root"></div> before the script tag but that didnt solve it. I am using webpack version 3.3.0.
Thanks. This is my webpack.config file.
var webpack = require('webpack');
var path = require('path');
var react = require('react');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var BUILD_DIR = path.resolve(__dirname, 'public');
var APP_DIR = path.resolve(__dirname, 'src/client/app');
var config = {
entry: APP_DIR + '/index.js',
output: {
path: BUILD_DIR,
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js?$/,
include: path.resolve(__dirname, 'src'),
exclude: [/node_modules/],
use: [{
loader: "babel-loader",
options: {
presets: ["stage-0","es2015","react"],
plugins: ["transform-class-properties", "react-html-attrs"]
}
}]
},
{
test: /\.css?$/,
use: ['style-loader', 'css-loader'],
},
{
test: /\.html?$/,
use: [
"htmllint-loader",
{
loader: "html-loader",
options: {}
}
]
}],
},
devServer: {
contentBase: path.join(__dirname, "public"),
compress: true,
port: 9000
},
plugins: [new HtmlWebpackPlugin({
title: 'My Project',
filename: 'main.html'
})]
}
module.exports = config;
Add index.js file in src/client/app/ and make sure you have import ReactDom from 'react-dom;
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class App extends Component{
render(){
return(
<div>
<h1>Hello App</h1>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementByID('root'));

Resources