i want to make my own ReactJS Typescript library and use it for other React JS Typescript projects. My library was built with Webpack 4 and has this structure:
|-src
| images
| | logo.svg
| button-component
| | index.tsx
| | styles.less
| container-component
| | index.tsx
| | styles.less
| index.tsx
| styes.less
My tsconfig.json file:
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"importHelpers": true,
"jsx": "react",
"esModuleInterop": true,
"sourceMap": false,
"baseUrl": ".",
"strict": true,
"paths": {
"#/*": ["src/*"]
},
"declaration": true,
"outDir": "./dist/",
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"strictNullChecks": false,
"removeComments": true,
"noLib": false,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"noEmitOnError": false
}
}
My webpack.config.js:
const path = require("path");
const WebpackMd5Hash = require("webpack-md5-hash");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
entry: {
main: "./src/index.tsx"
},
resolve: {
extensions: [".tsx", ".js"]
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: "index.js",
libraryTarget: "umd"
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin({
parallel: true,
cache: false,
extractComments: false,
terserOptions: {
output: {
comments: false,
},
},
}
)]
},
//devtool: 'source-map',
module: {
rules: [
{
test: /\.tsx?$/,
use: "ts-loader",
exclude: /node_modules/
},
{
test: /\.(less|css)$/,
use: [
{
loader: MiniCssExtractPlugin.loader
},
{
loader: "css-loader"
},
{
loader: "postcss-loader"
},
{
loader: 'less-loader'
}
]
},
{
test: /\.svg$/,
use: [
{
loader: 'svg-url-loader',
options: {
limit: 10000,
},
},
],
}
]
},
plugins: [
new CleanWebpackPlugin(path.resolve(__dirname, '../dist'), {
root: process.cwd()
}),
new MiniCssExtractPlugin({
filename: "styles.css"
}),
new WebpackMd5Hash()
]
};
index.tsx:
export { default as ButtonComponent } from './button-component';
export { default as ContainerComponent } from './container-component';
Button Component:
// #ts-nocheck
import React from 'react';
import { Button } from 'antd';
interface ButtonComponentState { }
interface ButtonComponentProps {
text: any
}
class ButtonComponent extends React.Component<ButtonComponentProps, ButtonComponentState> {
constructor(props: any) {
super(props);
}
render() {
return(<Button type={"primary"}>{this.props.text}</Button> )
}
}
export default ButtonComponent;
Container Component:
// #ts-nocheck
import React from 'react';
import { Card } from 'antd';
import { ButtonComponent } from '../button-component';
interface ContainerComponentState { }
interface ContainerComponentProps {
title: string
width: number
data: any
textBtn: any
}
class ContainerComponent extends React.Component<ContainerComponentProps, ContainerComponentState> {
constructor(props: any) {
super(props);
}
render() {
return(
<Card title={this.props.title} bordered={false} style={{ width: this.props.width }}>
{this.props.data}
<ButtonComponent text={this.props.textBtn}/>
</Card>
)
}
}
export default ContainerComponent;
After build with command: "webpack --env prod --mode production", i copies all the files in the dist folder to other ReactJS Typescript project, import them and use but i have these error messages:
Line 1:1: Expected an assignment or function call and instead saw an expression no-unused-expressions
Line 1:123: 'define' is not defined no-undef
Line 1:134: 'define' is not defined no-undef
Line 1:520: Expected an assignment or function call and instead saw an expression no-unused-expressions
...
This is the first line of built index.js file:
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define
I don't know how to correct this since Webpack built my library successfully without any error (just warning about the js file is big after build).
I also have another question: if i splitChunks those dependencies into a vendor.js file, do i need to import it in another project or just import my component from built index.js?
Related
We are currently migrating from Webpack to Vite. Therefore we started to switch our icons library to vite - so far this is working fine. This icon library is displayed in a storybook which is currently still bundled with webpack. Build process of the library runs without issues, but as soon as we want to display the icons (SVG-files) in the storybook we receive this warning and no icons are shown:
declaration.d.ts (icon lib)
declare module '*.svg' {
import * as React from 'react';
const ReactComponent: React.FC<React.SVGProps<SVGSVGElement>>;
export default ReactComponent;
}
vite.config.ts (icon lib)
import dts from '#rollup/plugin-typescript';
import svgr from 'vite-plugin-svgr'
import pluginReact from '#vitejs/plugin-react';
import { defineConfig } from 'vite';
import eslint from 'vite-plugin-eslint';
export default defineConfig(() => {
return {
plugins: [
eslint({
fix: true,
exclude: ['**/lib/**'],
}),
pluginReact({
jsxRuntime: 'classic',
}),
svgr(),
],
build: {
emptyOutDir: true,
target: 'esnext',
outDir: 'lib/',
lib: {
entry: './src/index.ts',
name: 'Icons',
fileName: 'index',
formats: ['umd'],
},
rollupOptions: {
plugins: [
dts({
allowSyntheticDefaultImports: true,
exclude: [/node_modules/],
}),
],
external: ['react', 'react-dom', 'styled-components'],
output: {
exports: 'named',
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'styled-components': 'Styled',
},
sourcemap: true,
},
},
},
};
ts.config.json (icon lib)
{
"compilerOptions": {
"declaration": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"importHelpers": true,
"isolatedModules": true,
"jsx": "react",
"target": "esnext",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"module": "commonjs",
"moduleResolution": "node",
"noUnusedLocals": true,
"noImplicitAny": true,
"pretty": true,
"removeComments": false,
"sourceMap": true,
"skipLibCheck": true,
"strict": true,
"resolveJsonModule": true
},
"include": ["./src", "declaration.d.ts"]
}
We use a wrapper component called SvgIcon.tsx
import * as React from 'react';
import styled from 'styled-components';
import type { IIconProps } from '../..';
import { StyledSvgIcon } from './SvgIcon.styled';
export type ISvgIconProps = {
component: React.FC<React.SVGProps<SVGSVGElement>>;
} & IIconProps;
export const SvgIcon: React.FC<ISvgIconProps> = (props) => {
const { className, id, size, component: Component } = props;
if (!Component) {
return null;
}
const StyledComponent = styled(Component)`
display: block;
fill: currentColor;
height: 100%;
width: 100%;
`;
return (
<StyledSvgIcon size={size} className={className}>
<StyledComponent id={id} x={'0px'} y={'0px'} width={size} height={size} />
</StyledSvgIcon>
);
};
an example file from the bundled library, IconAdd.js
import * as React from 'react';
import { SvgIcon } from '../../components/SvgIcon';
import { ReactComponent as Add } from '../../../assets/icons/a/Add.svg';
export const IconAdd = (props) => {
return React.createElement(SvgIcon, { ...props, component: Add });
};
For the storysbook we set this value in the webpack.config.js:
{
test: /\.svg?$/,
use: ['#svgr/webpack', 'url-loader'],
},
When I change the import like this:
import ReactComponent from '../../../assets/icons/a/Add.svg';
I receive this error:
Failed to execute 'createElement' on 'Document': The tag name provided ('04516931d13db305ccbc.svg') is not a valid name.
I have a project created with React, Typescript & Vite. It gives this error when I declare an interface for a component. I have included the files below that I think will be causing the issue. Let me know if you think anyother file is causing this issue.
[plugin:vite:esbuild] Transform failed with 1 error:
C:/Users/Aqib/Desktop/React/New-Agrod-Frontend/src/components/ui/IconTextField.tsx:3:10: ERROR: Expected ";" but found "Props"
C:/Users/Aqib/Desktop/React/New-Agrod-Frontend/src/components/ui/IconTextField.tsx:4:10
Expected ";" but found "Props"
1 | import RefreshRuntime from "/#react-refresh";let prevRefreshReg;let prevRefreshSig;if (import.meta.hot) { if (!window.__vite_plugin_react_preamble_installed__) { throw new Error( "#vitejs/plugin-react can't detect preamble. Something is wrong. " + "See https://github.com/vitejs/vite-plugin-react/pull/11#discussion_r430879201" ); } prevRefreshReg = window.$RefreshReg$; prevRefreshSig = window.$RefreshSig$; window.$RefreshReg$ = (type, id) => { RefreshRuntime.register(type, "C:/Users/Aqib/Desktop/React/New-Agrod-Frontend/src/components/ui/IconTextField.tsx" + " " + id) }; window.$RefreshSig$ = RefreshRuntime.createSignatureFunctionForTransform;}import { BaseTextFieldProps, Box, TextField } from '#mui/material';
2 | import { FC, ReactNode } from 'react';
3 | interface Props extends BaseTextFieldProps {
| ^
4 | icon?: ReactNode | ReactNode[];
5 | }
at failureErrorWithLog (C:\Users\Aqib\Desktop\React\New-Agrod-Frontend\node_modules\esbuild\lib\main.js:1604:15)
at C:\Users\Aqib\Desktop\React\New-Agrod-Frontend\node_modules\esbuild\lib\main.js:837:29
at responseCallbacks.<computed> (C:\Users\Aqib\Desktop\React\New-Agrod-Frontend\node_modules\esbuild\lib\main.js:701:9)
at handleIncomingPacket (C:\Users\Aqib\Desktop\React\New-Agrod-Frontend\node_modules\esbuild\lib\main.js:756:9)
at Socket.readFromStdout (C:\Users\Aqib\Desktop\React\New-Agrod-Frontend\node_modules\esbuild\lib\main.js:677:7)
at Socket.emit (node:events:513:28)
at addChunk (node:internal/streams/readable:324:12)
at readableAddChunk (node:internal/streams/readable:297:9)
at Readable.push (node:internal/streams/readable:234:10)
at Pipe.onStreamRead (node:internal/stream_base_commons:190:23
Code causing the bug
import { BaseTextFieldProps, Box, TextField } from '#mui/material'
import { FC, ReactNode } from 'react'
interface Props extends BaseTextFieldProps {
icon?: ReactNode | ReactNode[]
}
const IconTextField: FC<Props> = ({ icon, ...rest }) => {
return (
<Box sx={{ position: 'relative' }}>
<TextField
{...rest}
variant='outlined'
size='small'
InputProps={{
style: {
backgroundColor: 'white',
outline: 'none',
borderRadius: 10,
},
}}
fullWidth
/>
<Box sx={{ position: 'absolute', top: 10, left: -30 }}>{icon}</Box>
</Box>
)
}
export default IconTextField
tsconfig.ts
{
"compilerOptions": {
"baseUrl": ".",
"target": "ESNext",
"useDefineForClassFields": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": true,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
"paths": {
"#Pages/*": ["./src/pages/*"],
"#Layout/*": ["./src/layouts/*"],
"#Assets/*": ["./src/assets/*"],
"#Components/*": ["./src/components/*"]
}
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
vite.config.ts
import react from '#vitejs/plugin-react'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'
// https://vitejs.dev/config/
export default defineConfig({
esbuild: {
loader: 'jsx',
},
root: './',
build: {
outDir: './build',
},
optimizeDeps: {
esbuildOptions: {
loader: {
'.js': 'jsx',
'.ts': 'tsx',
},
},
},
plugins: [react(), tsconfigPaths()],
})
I tried searching for this bug but couldn't find anything.
If you change the loader it should work
import react from '#vitejs/plugin-react';
import { defineConfig } from 'vite';
import tsconfigPaths from 'vite-tsconfig-paths';
// https://vitejs.dev/config/
export default defineConfig({
esbuild: {
loader: 'tsx',
},
root: './',
build: {
outDir: './build',
},
optimizeDeps: {
esbuildOptions: {
loader: {
'.js': 'jsx',
'.ts': 'tsx',
},
},
},
plugins: [react(), tsconfigPaths()],
});
I've been trying to figure out how to have my declared module be found when I shallow render a component using enzyme in my jest unit tests. I have a custom declared module like so:
// index.d.ts
declare module "_aphrodite" {
import {StyleDeclarationValue} from "aphrodite";
type CSSInputType = StyleDeclarationValue | false | null | void;
interface ICSSInputTypesArray extends Array<CSSInputTypes> {}
export type CSSInputTypes = CSSInputType | CSSInputType[] | ICSSInputTypesArray;
}
Which is used by a component of mine called closeButton:
// closeButton.tsx
import {CSSInputTypes} from "_aphrodite";
export interface ICloseButtonProps {
onClick: (event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void;
cssStyles?: CSSInputTypes;
}
#injectable()
#observer
#autobind
export class CloseButton extends React.Component<ICloseButtonProps> {
// implementation
}
And a simple unit test that shallow renders a component:
// closeButton.test.tsx
import {shallow} from "enzyme";
import {CloseButton} from "../../common";
import * as React from "react";
describe("Common - Close Button", () => {
it("Shallow Render", () => {
const component = shallow(<CloseButton onClick={null}/>);
console.log(component);
});
});
When I run the test, I get the following error:
Which is strange because the closeButton class doesn't throw any compilation errors and maps the module fine. Same goes with when I run my project locally, it doesn't throw any run time error about not being able to find the _aphrodite module. It seems it's just with testing that this comes up.
Now I've tried to change various settings in my jest.config.json, tsconfig.json, and webpack.config.js settings with no luck. I'm hoping someone with more experience than I would know what needs to be done in order to make my _aphrodite module found when running a shallow render on a component.
Below are the settings for the aforementioned files:
// jest.config.json
{
"verbose": true,
"moduleFileExtensions": [
"ts",
"tsx",
"js"
],
"moduleDirectories": [
"node_modules",
"src"
],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|svg)$": "<rootDir>/src/components/__tests__/_transformers/fileTransformer.js"
},
"transform": {
"\\.(ts|tsx)$": "ts-jest"
},
"setupFiles": [
"<rootDir>/src/components/__tests__/setup.ts"
],
"testRegex": "(/__tests__/\\.*|(\\.|/)(test))\\.tsx?$",
"testURL": "http://localhost/",
"collectCoverage": false,
"timers": "fake"
}
// tsconfig.json
{
"compileOnSave": true,
"compilerOptions": {
"rootDir": "./src",
"outDir": "./build/",
"sourceMap": true,
"noImplicitAny": true,
"module": "esnext",
"target": "es2018",
"jsx": "react",
"watch": false,
"removeComments": true,
"preserveConstEnums": true,
"inlineSourceMap": false,
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"lib": [
"dom",
"dom.iterable",
"es2018",
"esnext"
],
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"moduleResolution": "node",
"isolatedModules": false
},
"include": [
"./src/**/*"
],
"exclude": [
"./node_modules"
]
}
// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
const webpack = require('webpack');
const dotenv = require('dotenv');
const fs = require('fs'); // to check if the file exists
module.exports = () => {
return {
plugins: []
};
};
/**
* DevServer
*/
const devServer = {
inline: true,
host: "localhost",
port: 3000,
stats: "errors-only",
historyApiFallback: true,
watchOptions: {
poll: true
},
};
module.exports.getEnv = () => {
// Create the fallback path (the production .env)
const basePath = __dirname + '/.env';
// We're concatenating the environment name to our filename to specify the correct env file!
const envPath = basePath + ".local";
// Check if the file exists, otherwise fall back to the production .env
const finalPath = fs.existsSync(envPath) ? envPath : basePath;
// call dotenv and it will return an Object with a parsed key
const finalEnv = dotenv.config({path: finalPath}).parsed;
// reduce it to a nice object, the same as before
const envKeys = Object.keys(finalEnv).reduce((prev, next) => {
prev[`process.env.${next}`] = JSON.stringify(finalEnv[next]);
return prev;
}, {});
return new webpack.DefinePlugin(envKeys);
};
/**
* Plugins
*/
const plugins = [
new HtmlWebpackPlugin({
template: "./index.html"
}),
module.exports.getEnv()
];
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: __dirname + "/build",
publicPath: "/"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{test: /\.tsx?$/, loader: "ts-loader"},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{enforce: "pre", test: /\.js$/, loader: "source-map-loader", exclude: [/node_modules/, /build/, /__test__/]},
{test:/\.css$/, use:['style-loader','css-loader'] },
{test:/\.(png|svg)$/, loader: "url-loader"},
{test:/\.mp3$/, loader: "url-loader" }
]
},
plugins: plugins,
devServer: devServer,
mode: "development",
performance: {
hints: false
}
};
And here is my project structure:
Feel free to ask if more information is needed.
Turns out I just needed to add it to the list of setup files in jest.config.json
// jest.config.json
"setupFiles": [
"<rootDir>/src/components/__tests__/setup.ts",
"<rootDir>/src/aphrodite/index.ts"
],
I am setting up webpack 4 to run with React and TypeScript.
If I attempt to use the dynamic imports feature, the build fails with: JSX element type 'Hello' does not have any construct or call signatures.
I have attempted various configuration values in tsconfig.json to no avail. I have ran out of options.
My current setup is this.
tsconfig.js:
{
"compilerOptions": {
"target": "es5",
"module": "esnext",
"lib": [
"dom",
"es6"
],
"jsx": "react",
"declaration": false,
"sourceMap": false,
"inlineSourceMap": true,
"outDir": "./public/static/",
"strict": true,
"moduleResolution": "node",
"noImplicitAny": true,
"preserveConstEnums": true,
"removeComments": false,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": [
"./resources/assets/js/**/*"
]
}
webpack.config.js:
const { resolve } = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ManifestPlugin = require('webpack-manifest-plugin');
const WEBPACK_ASSETS_PUBLIC_PATH = '/';
module.exports = {
entry: {
app: ['./resources/assets/js/App.tsx'],
vendor: ['react', 'react-dom']
},
output: {
path: resolve(__dirname, 'public', 'static'),
publicPath: WEBPACK_ASSETS_PUBLIC_PATH,
filename: 'js/[name].[hash].js',
chunkFilename: 'js/[name].[hash].js'
},
optimization: {
runtimeChunk: 'single',
minimize: true
},
devtool: 'inline-source-map',
devServer: {
contentBase: resolve(__dirname, 'public', 'static')
},
resolve: {
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx']
},
module: {
rules: [
{
test: /\.(ts|tsx)$/,
loader: 'awesome-typescript-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: resolve(__dirname, 'index.html')
}),
new ManifestPlugin({
publicPath: WEBPACK_ASSETS_PUBLIC_PATH
})
]
};
App.tsx:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
(async () => {
let Hello = await import('./components/Hello');
ReactDOM.render(<Hello compiler="TypeScript" framework="React" bundler="webpack" />, document.getElementById('root'));
})();
Hello.tsx:
import * as React from 'react';
interface IHelloProps {
compiler: string,
framework: string,
bundler: string
};
export default class Hello extends React.Component<IHelloProps, {}> {
render () {
return <h1>This is a {this.props.framework} application using {this.props.compiler} with {this.props.bundler}.</h1>;
}
};
If going the static way:
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import Hello from './components/Hello';
ReactDOM.render(<Hello compiler="TypeScript" framework="React" bundler="webpack" />, document.getElementById('root'));
Then it works flawlessly.
What am I doing wrong with the dynamic imports that it throws errors? From what I've gathered, it's a build time error..
Perhaps this is due to the interaction of async imports and default exports, I'd try it without the default export.
So export the class like this:
export class Hello extends React.Component<IHelloProps, {}> {
// ...
}
and import it like this:
let { Hello } = await import('./components/Hello');
Im converting React app to use Typescript. And Im getting the following error:
ERROR in [at-loader] ./src/components/Services/Services.tsx:34:29
TS7017: Element implicitly has an 'any' type because type 'typeof "/Users/path/to/project/src/components/Services/Services.css"' has no index signature.
Webpack config
const path = require("path");
module.exports = {
context: path.join(__dirname, "src"),
entry: ["./index.js"],
output: {
path: path.join(__dirname, "www"),
filename: "bundle.js"
},
devtool: "sourcemap", // has to be removed in production
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"],
modules: [path.join(__dirname, "node_modules")]
},
module: {
rules: [
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
{
test: /\.(jsx?)$/,
exclude: /node_modules/,
use: ["babel-loader"]
},
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" },
{
test: /\.css$/,
use: [
"style-loader",
{
loader: "typings-for-css-modules-loader",
options: {
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]"
// namedExport: true
}
},
"postcss-loader"
]
},
{
test: /\.(jpeg|jpg|png|gif|svg)$/i,
use: [
{
loader: "file-loader",
options: {
name: "[name].[ext]",
outputPath: "images/"
}
}
]
}
]
}
};
And this is my tsconfig:
{
"compilerOptions": {
"outDir": "./www/",
"sourceMap": true,
"noImplicitAny": true,
"alwaysStrict": true,
"strictNullChecks": true,
"module": "es6",
"moduleResolution": "node",
"jsx": "react",
"target": "es5",
"allowJs": true,
"allowSyntheticDefaultImports": true
},
"include": ["./src/**/*"]
}
This is the Services.tsx file:
import React from "react";
import ReactDOM from "react-dom";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import queryString from "query-string";
import * as styles from "./Services.css";
import globalStyles from "../../styles/global.css";
import SubHeader from "../common/SubHeader";
class Services extends React.Component<any, any> {
constructor() {
super();
}
render() {
return (
<div className={styles["services"]}>
<SubHeader text={"MY SERVICES"} />
<div className={styles["body"]}>
//loop over props and render
</div>
</div>
);
}
}
function mapStateToProps(state: any) {
return {
services: state.services,
vehicles: state.vehicles
};
}
export default connect(mapStateToProps)(Services);
This is the Services.css file:
.services {
padding-top: 64px;
.body {
margin: 16px;
}
}
And this is the Services.css.d.ts file created by typings-for-css-modules-loader:
export interface IServicesCss {
'services': string;
'body': string;
}
export const locals: IServicesCss;
Im using typescript: "^2.7.2" and typings-for-css-modules-loader: "^1.7.0"
I cant figure out what the error means. I searched online and all the resource mention about index signature related. Since Im new to Typescript, cant figure out what it takes to fix the issue.
Try this might help article for style loader
Typescript is unable to load the css files or is unable to find the declarations for the same please do try these webpack.config.js changes of adding a style-loader in plugins might help and your related problem will be solved
The error/warning was coming because namedExport was not set as true. (I had it commented out)
Note: even with namedExport: false, the code will run. But the .css.d.ts file created will be of the following structure:
export interface IServiceDetailCardCss {
'service-detail-card': string;
'left-col': string;
'amount': string;
'symbol': string;
}
export const locals: IServiceDetailCardCss;
But, if you set namedExport: true, each classname will be an individual named export, like this:
export const serviceDetailCard: string;
export const leftCol: string;
export const amount: string;
export const symbol: string;
..and you will be able to reference them like styles.serviceDetailCard in your JSX.
Note: If you enable namedExport: true, you should also couple it with camelCase: true, to convert classnames of type some-classname to someClassname.