I have this new project being assembled with Webpack 5
+ React 16
+ TypeScript 4
and willing to use SASS
.
I have set all loaders, but yet the class does not apply on the html elements, when I say "class" it's exactly what I mean, if I style directly an element it does work.
I my main.scss
main file (which is imported in the main app file App.tsx
) if I put:
body { background-color: red; }
This works Ok!
But if I try to set the style using class like this:
.main-body-style {
background-color: red;
}
...
<body className="main-body-style">...</body>
This doesn't work, super weird!!
My very basic webpack.config.ts
:
import path from "path";
import { Configuration, DefinePlugin } from "webpack";
import ForkTsCheckerWebpackPlugin from "fork-ts-checker-webpack-plugin";
import pjson from "./package.json";
const now = new Date();
const buildVersion = `v${pjson.version}-${
now.getDate().toString().padStart(2, "0") +
(now.getMonth() + 1).toString().padStart(2, "0") +
now.getFullYear() +
"." +
now.getHours().toString().padStart(2, "0") +
now.getMinutes().toString().padStart(2, "0")
}`;
const urlStoreMessage = "htpp://";
const __ = (argToStringfy: string) => JSON.stringify(argToStringfy);
const config: Configuration = {
entry: "./src/index.tsx",
module: {
rules: [
{
test: /\.(ts|js)x?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript",
],
},
},
},
{
test: /\.s(a|c)ss$/,
include: [path.resolve(__dirname, "src/assets")],
use: [
"style-loader",
{
loader: "css-loader",
options: { modules: true },
},
"sass-loader",
],
},
],
},
plugins: [
new ForkTsCheckerWebpackPlugin({
async: false,
eslint: {
files: "./src/**/*.{ts,tsx,js,jsx}", //files: "./src/**/*",
},
}),
new DefinePlugin({
"process.env": process.env.production || !process.env.development,
BUILD_VERSION: __(buildVersion),
URL_STORE_MESSAGE: __(urlStoreMessage),
}),
],
resolve: {
extensions: [".tsx", ".ts", ".js"],
},
output: {
path: path.resolve(__dirname, "build"),
filename: "bundle.js",
},
devtool: "source-map",
devServer: {
static: path.join(__dirname, "build"),
compress: true,
liveReload: true,
open: false,
port: 4000,
},
};
export default config;
Basic .babelrc
:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"regenerator": true
}
]
]
}
Basic tsconfig.json
:
{
"compilerOptions": {
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"allowSyntheticDefaultImports": true,
"skipLibCheck": true,
"esModuleInterop": true,
"strict": true,
"sourceMap": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true, // Babel is going to generate the typescript code
"jsx": "react", //
"module": "commonjs"
},
"include": ["src"]
}
.eslintrc.json
:
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "react-hooks"],
"extends": [
"plugin:react/recommended",
"plugin:@typescript-eslint/recommended"
],
"rules": {
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "warn",
"react/prop-types": "off"
},
"settings": {
"react": {
"pragma": "React",
"version": "detect"
}
}
}
package.json
:
...
"dependencies": {
"axios": "^0.24.0",
"bootstrap": "^4.4.1",
"history": "^5.1.0",
"react": "^16.8.6",
"react-bootstrap": "^1.6.1",
"react-bootstrap-icons": "^1.6.1",
"react-bootstrap-table": "^4.3.1",
"react-dom": "^16.8.6",
"react-router-dom": "^5.2.0",
"sass": "^1.43.4"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-runtime": "^7.16.0",
"@babel/preset-env": "^7.16.0",
"@babel/preset-react": "^7.16.0",
"@babel/preset-typescript": "^7.16.0",
"@babel/runtime": "^7.16.0",
"@types/bootstrap": "^5.1.6",
"@types/fork-ts-checker-webpack-plugin": "^0.4.5",
"@types/node-sass": "^4.11.2",
"@types/react": "^16.8.6",
"@types/react-bootstrap": "^0.32.28",
"@types/react-dom": "^16.8.6",
"@types/react-router-dom": "^5.3.2",
"@types/webpack": "^5.28.0",
"@types/webpack-dev-server": "^4.3.1",
"@typescript-eslint/eslint-plugin": "^5.3.0",
"@typescript-eslint/parser": "^5.3.0",
"babel-loader": "^8.2.3",
"css-loader": "^6.5.1",
"css-modules-typescript-loader": "^4.0.1",
"eslint": "^7.32.0",
"eslint-plugin-react": "^7.26.1",
"eslint-plugin-react-hooks": "^4.2.0",
"fork-ts-checker-webpack-plugin": "^6.4.0",
"html-webpack-plugin": "^5.5.0",
"node-sass": "^6.0.1",
"sass-loader": "^12.3.0",
"style-loader": "^3.3.1",
"ts-node": "^10.4.0",
"typescript": "^4.4.4",
"webpack": "^5.62.1",
"webpack-cli": "^4.9.1",
"webpack-dev-server": "^4.4.0"
}
...
And in a very basic App.tsx file:
import React from "react";
import TopBarMenu from "../components/TopBarMenu";
import "../assets/styles/main.scss";
const App: React.FC = () => {
return (
<>
<TopBarMenu />
</>
);
};
export default App;
What am I missing here? I have other projects with Webpack and React, but without Typescript and with Webpack 4.
In webpack.config.ts , your have enabled modules in css-loader options for all css/scss files , and they will be treated as css module files. refer to : https://github.com/css-modules/css-modules for usage. a better implementation is to have 2 rules , one to handle the normal css/scss files and another to handle css/scss modules, like this :
{
test: /\.module\.(sa|sc|c)ss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { modules: true }
},
'sass-loader'
]
},
{
test: /\.(sa|sc|c)ss$/,
exclude: /\.module\.(sa|sc|c)ss$/,
use: ['style-loader', 'css-loader', 'sass-loader']
},
then all *.scss/css/sass files will be treated as normal , and all *.module.scss/css/sass will be treated as css modules
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With