Unable to import sass files in react - reactjs

I'm using the following boilerplate : https://github.com/spravo/typescript-react-express
I designed a first component : Button
import * as React from 'react';
import './button.scss';
export interface IButton {
value: string;
onClick: () => void;
}
class Button extends React.Component<IButton, {}> {
public render () {
return (
<div className='Button'>
<button onClick={this.props.onClick} className='Button__btn'>
{this.props.value}
</button>
</div>
);
}
}
export default Button;
And in the button.scss I have this simple line :
.Button {
background-color: red;
}
But I get the following error :
(function (exports, require, module, __filename, __dirname) { .Button {
SyntaxError: Unexpected token .
This is my webpack config (quite the same as the one from the repo) except the config.common.js for the webpack migration :
'use strict';
const path = require('path');
const webpack = require("webpack");
const config = require('../config')(process.env.NODE_ENV);
const vendors = require('./vendor');
const NODE_ENV = process.env.NODE_ENV || 'development';
module.exports = function getConfig(dirname) {
return {
target: 'web',
context: path.resolve(dirname),
stats: {
chunks: false,
colors: true,
},
entry: {
vendor: vendors
},
resolve: {
extensions: [ '.ts', '.tsx', '.js', '.scss', '.css' ],
modules: [
path.resolve(__dirname, '..', 'src'),
path.resolve(__dirname, '..', 'node_modules'),
]
},
output: {
path: config.PUBLIC_FOLDER,
filename: '[name].[hash].js',
chunkFilename: '[name].[chunkhash].js',
publicPath: config.PUBLIC_PATH
},
module: {
rules: []
},
optimization:{
splitChunks:{
name: 'vendor'
}
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
// new webpack.optimize.CommonsChunkPlugin({
// name: 'vendor'
// }),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(NODE_ENV)
},
__CLIENT__: true,
__SERVER__: false,
__DEV__: NODE_ENV === 'development',
__TEST__: false
})
]
};
};
The Css loaders :
'use strict';
const isDevelopment = (process.env.NODE_ENV || 'development') === 'development';
const autoprefixer = require('autoprefixer');
module.exports = {
scssLoader: [
{
loader: 'css-loader',
options: {
minimize: !isDevelopment,
sourceMap: isDevelopment
}
},
{
loader: 'postcss-loader',
options: {
sourceMap: isDevelopment,
plugins: [
autoprefixer({
browsers:['ie >= 8', 'last 4 version']
})
]
}
},
{
loader: 'sass-loader',
options: {
sourceMap: isDevelopment
}
}
]
};
It seems that the only scss that works is in the styles/index.scss but I don't get why it doesn't take other scss files.
My tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"baseUrl" : "./src",
"target": "es5",
"jsx": "react",
"alwaysStrict": true,
"sourceMap": true,
"outDir": "dist",
"lib": [
"dom",
"es2015",
"es5",
"es6"
]
},
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"typings"
],
"exclude": [
"node_modules"
]
}

It is really weird that your webpack config "module.rules" is an empty array!
That is where your loader settings should be added.
If I were you, I would have copied the content of css-loaders config file and pasted in your webpack.config.js file. Make sure you store it in a normal variable/object instead of module.exports.
This is how my webpack config looks like:
const styleLoader = {
test: /\.(scss)$/,
include: path.resolve(__dirname, 'src'),
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
sourceMap: true,
minimize: true
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: true,
config: {
path: path.join(__dirname, 'postcss.config.js')
}
}
}, {
loader: 'sass-loader',
options: { sourceMap: true }
}
]
})
};
And then my webpack config looks like below. Pay attention to the modules.rules section:
module.exports = {
entry: {
app: ['babel-polyfill', 'whatwg-fetch', srcPath('index.js')],
silentrenew: [srcPath('silentrenew.js')]
},
output: {
path: path.resolve(__dirname, 'build'),
publicPath: '/',
filename: '[name].js'
},
devtool: 'source-map',
plugins: [
htmlPlugin('index.html', 'app'),
new ExtractTextPlugin('bundle.css'),
],
module: {
rules: [
babelLoader,
fontLoader,
svgLoader,
styleLoader
]
}
};

Related

Problems with images in react application

When using images in react, there is either a problem with typescript, or the image breaks on the site.
To solve the problem, I tried:
Add url-loader and file-loader to the webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const BUILD_PATH = path.resolve(__dirname, './build');
const SRC_PATH = path.resolve(__dirname, './src/');
const PUBLIC_PATH = path.resolve(__dirname, './public')
module.exports = {
entry: SRC_PATH + '/index.tsx',
output: {
path: BUILD_PATH,
filename: 'bundle.js',
},
mode: process.env.NODE_ENV || 'development',
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
extensions: [ '.tsx', '.ts', '.js' ],
},
devServer: {
static: PUBLIC_PATH,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader'
},
{
test: /\.(css|scss)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.module.css$/,
use: [
{
loader: "css-loader",
options: {
modules: true,
},
},
],
},
{
test: /\.(jpg|png|svg)$/,
loader: 'url-loader',
options: {
limit: 8192,
},
},
{
test: /\.(jpg|jpeg|png|gif|mp3|svg)$/,
use: ['file-loader']
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'public', 'index.html'),
}),
],
};
Import images as components
import React from 'react';
import logo from './header-logo.svg';
import styles from './Header.module.scss';
export const Header = () => {
return <header className={styles.header}>
<img src={logo} />
</header>
};
Create the images.d.ts file in the src/types directory
declare module "*.svg" {
const content: any;
export default content;
}
And I even tried svgr..
But nothing helped. If I delete the images.d.ts file, typescript cannot detect the module when importing. When using images.d.ts, vscode does not show errors, but the picture is not displayed in the browser, and instead of the normal path, something strange data:image/svg+xml;base64,ZXhwb3J0IGRlZmF1bHQgX193ZWJwYWNrX3B1YmxpY19wYXRoX18gKyAiZWMzYzM1Nzg3YTljZTMyMzE4M2NmMzM2Y2EzMDBkOTkuc3ZnIjs=
And just in case, I attach tsconfig.json
{
"compilerOptions": {
"baseUrl": "./",
"outDir": "./build/",
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"plugins": [
{
"name": "typescript-plugin-css-modules"
},
],
},
}
I'm new to react so please don't judge strictly for stupid mistakes. I would appreciate any advice!
You can use svg-url-loader npm module. in webpack.config,js
{
test: /\.svg$/,
use: [
{
loader: "svg-url-loader",
options: {
limit: 10000,
},
},
],
},
in your component
// pass a correct path
import logo from './header-logo.svg';
<img src={logo} alt="" />
After some thought, I came to the conclusion that perhaps the problem occurred due to a loaders conflict. Leaving only the file-loader and deleting the url-loader, I was able to solve the problem. I hope my solution can help someone in the future.
My files now look like this:
webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');
const SRC_PATH = path.resolve(__dirname, './src');
const BUILD_PATH = path.resolve(__dirname, './build');
const PUBLIC_PATH = path.resolve(__dirname, './public')
module.exports = {
entry: SRC_PATH + '/index.tsx',
output: {
path: BUILD_PATH,
filename: 'bundle.js',
},
mode: process.env.NODE_ENV || 'development',
resolve: {
modules: [SRC_PATH, 'node_modules'],
extensions: [ '.tsx', '.ts', '.js' ],
},
devServer: {
static: PUBLIC_PATH,
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader']
},
{
test: /\.tsx?$/,
exclude: /node_modules/,
loader: 'ts-loader'
},
{
test: /\.(css|scss)$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
},
{
test: /\.module.css$/,
use: [
{
loader: "css-loader",
options: {
modules: true,
},
},
],
},
{
test: /\.(jpg|jpeg|png|gif|mp3|svg)$/,
use: ['file-loader']
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: PUBLIC_PATH + '/index.html',
}),
],
};
A imges.d.ts file for type resolution for typescript
declare module "*.jpg";
declare module "*.png";
declare module "*.svg";

'SocketClient is not a constructor' in react-refresh-webpack-plugin

I have a typescript react project where I try to add the react-refresh-webpack-client and get this error:
my webpack config:
import HtmlWebpackPlugin from 'html-webpack-plugin';
import UglifyJsPlugin from 'uglifyjs-webpack-plugin';
import ReactRefreshWebpackPlugin from '#pmmmwh/react-refresh-webpack-plugin';
import ReactRefreshTypeScript from 'react-refresh-typescript';
import { HotModuleReplacementPlugin } from 'webpack';
const isDevelopment = process.env.NODE_ENV !== 'production';
module.exports = {
resolve: {
extensions: [".ts", ".tsx", ".js", ".jsx"]
},
optimization: {
minimizer: [new UglifyJsPlugin()],
splitChunks: {
chunks: 'all'
}
},
mode: isDevelopment ? 'development' : 'production',
devServer: {
port: process.env.WEBPACK_PORT,
historyApiFallback: true,
hot: true,
},
module: {
rules: [
{
test: /\.[jt]sx?$/,
exclude: /node_modules/,
use: [
{
loader: require.resolve('ts-loader'),
options: {
getCustomTransformers: () => ({
before: isDevelopment ? [ReactRefreshTypeScript()] : [],
}),
// `ts-loader` does not work with HMR unless `transpileOnly` is used.
transpileOnly: isDevelopment,
},
},
],
},
{ enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: 'source-map-loader'
},
{
test: /\.(png|jpe?g|gif)$/i,
type: 'asset/resource'
},
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: './client/index.html',
filename: './index.html',
}),
isDevelopment && new HotModuleReplacementPlugin(),
isDevelopment && new ReactRefreshWebpackPlugin(),
],
entry: {
main: ['./client/index.tsx'],
vendor: ['lodash', 'react', '#material-ui/core'],
},
devtool: 'source-map'
};
here is my tsconfig file:
{
"compilerOptions": {
"target": "es5",
"module": "es2015",
"jsx": "react",
"strict": true,
"alwaysStrict": true,
"noImplicitReturns": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"exclude": [
"node_modules"
]
}
I already removed react-hot-loader from my code.
can't find any example of react-refresh with typescript, what am I missing?
what could be my problem? thank you!
I would use export default { instead of module.exports = {
You need to use the latest refresh plugin (0.5.0), explanation is in this issue.

Cannot find module Error (React, TypeScript, Webpack)

Want to run app, but get the following error:
This is my project structure:
this is my app module
i use export and also export default are same:
app component
and the imports of the module:
My webpack :
const devSever = (isDev) => !isDev ? {} : {
devServer: {
open: true,
hot: true,
port: 7070,
contentBase: path.join(__dirname,'public')
}
};
const esLintPlugin = (isDev) => isDev ? [] : [new ESLintPlugin({ extensions: ['.ts', '.tsx ','.js']}) ]
module.exports = ({develop}) => ( {
mode: develop ? 'development': 'production',
devtool: develop ? 'inline-source-map' : false,
entry:{
app: './src/index.tsx',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
assetModuleFilename: 'assets/[hash][ext]' //may be hash
},
module: {
rules: [
{
test: /\.(ts|tsx|js)$/,
use: 'ts-loader',
exclude: /node_modules/
},
{
test: /\.(?:ico|gif|png|jpg|jpeg|svg)$/i,
type: 'asset/resource'
},
{
test: /\.(woff(2)?|eot|ttf|otf)$/i,
type: 'asset/resource'
},
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader,'css-loader']
}
]
},
resolve: {
extensions: ['.tsx','.ts','.js']
},
plugins: [
new CircularDependencyPlugin({
exclude: /a\.js|node_modules/,
include: /dir/,
failOnError: true,
allowAsyncCycles: false,
cwd: process.cwd()
}),
new HtmlWebpackPlugin({
template: './src/index.html'
}),
new MiniCssExtractPlugin({
filename: 'style.css'
}),
new CopyPlugin({
patterns: [{from: './public' }]
}),
new CleanWebpackPlugin({cleanStaleWebpackAssets: false}),
...esLintPlugin(develop)
],
...devSever(develop)
});
it's all work good only if there are not imports and if i write code only in one component
you check out tsconfig.json
{
"include": ["src/**/*"],
"compilerOptions": {
"rootDir": "./src"
}
}

Webpack 5 Aliases not resolving correctly

I've just updated my project from webpack 3 to 5 and now none of my imports/aliases are working anywhere.
Webpack is in the root directory.
webpack.config.js Below:
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
var mode = process.env.NODE_ENV || 'development';
const config = {
entry: {
main: path.resolve(__dirname, 'src/index.js'),
Dashboard: path.resolve(__dirname, 'src/shared/pages/dashboard/index.js'),
Driver: path.resolve(__dirname, 'src/shared/pages/driver/index.js'),
Drivers: path.resolve(__dirname, 'src/shared/pages/drivers/index.js'),
FAQ: path.resolve(__dirname, 'src/shared/pages/faq/index.js'),
Home: path.resolve(__dirname, 'src/shared/pages/home/index.js'),
Job: path.resolve(__dirname, 'src/shared/pages/job/index.js'),
Jobs: path.resolve(__dirname, 'src/shared/pages/jobs/index.js'),
Signin: path.resolve(__dirname, 'src/shared/pages/signin/index.js')
} ,
// performance: {
// hints: "error"
// },
output: {
filename: '[name].[contenthash].js'
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor:{
test: /[\\/]node_modules[\\/]/,
name(module){
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
return `npm.${packageName.replace('#', '')}`;
}
}
}
}
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader',
}
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.s(a|c)ss$/,
use: [ 'style-loader', 'css-loader','sass-loader'],
},
{
test: /\.(jpe?g|png|gif|woff|woff2|eot|ttf|svg)(\?[a-z0-9=.]+)?$/,
use: 'url-loader?limit=100000'
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename: 'bundle.scss'}
),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "src", "index.html")
})
],
resolve: {
alias: {
shared: path.resolve(__dirname, 'src/shared/'),
client: path.resolve(__dirname, 'src/client/'),
server: path.resolve(__dirname, 'src/server/'),
sass: path.resolve(__dirname, 'src/sass/')
},
extensions: ['.js', '.sass', '.scss']
},
devtool: (mode === 'development') ? 'inline-source-map' : false,
mode: mode,
devServer: {
disableHostCheck: true,
historyApiFallback: true,
inline: true,
contentBase: path.join(__dirname, "dist"),
publicPath: '/provider/',
hot: true,
proxy: {
'/api/**': {
target: 'http://localhost:3333/',
secure: false,
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
};
module.exports = config;
Example Import that isn't working:
import { meFromToken } from 'shared/actions/user'
Change that fixes it:
import {meFromToken} from '../../actions/user'
What am I doing wrong? I don't want to refactor all our imports because the aliases aren't resolving properly.
You'd need to add the same config for tsconfig.json or jsconfig.json
Eg:
{
"compilerOptions": {
"baseUrl": ".",
"module": "commonjs",
"paths": {
"#shared/*": ["./src/shared/*"]
}
}
}

only one install of babel polyfill is allowed when running karma/enzyme test

When I run karma test with enzyme I get an error:
only one instance of babel-polyfill is allowed at ...
The is the test file that caused this error:
import React from 'react';
import { Provider } from 'react-redux';
import configureStore from '../../src/common/store/configureStore';
import { shallow,mount } from 'enzyme';
import ChatContainer from '../../src/common/containers/ChatContainer';
const initialState = window.__INITIAL_STATE__;
const store = configureStore(initialState);
describe('ChatContainer Component', () => {
let Component;
beforeEach(() => {
Component =
mount(<Provider store={store}>
<ChatContainer />
</Provider>);
});
it('should render', () => {
expect(Component).toBeTruthy();
});
});
This is the only file so far that is triggering this error so I dont know why..
I am not sure if it is the babel-plugin-transform-class-properties in my karma config that is causing this issue:
/* eslint-disable no-var */
var path = require('path');
module.exports = function webpackConfig(config) {
config.set({
basePath: '',
frameworks: ['jasmine'],
files: [
'test/components/*.spec.js',
// 'test/test_index.js',
],
preprocessors: {
'src/js/**/*.js': ['webpack', 'sourcemap'],
'test/**/*.spec.js': ['webpack', 'sourcemap'],
// 'test/test_index.js': ['webpack', 'sourcemap'],
},
webpack: {
devtool: 'inline-source-map',
alias: {
cheerio: 'cheerio/lib/cheerio',
},
module: {
loaders: [{
test: /\.js$/,
loader: 'babel',
query: {
presets: ['airbnb'],
plugins: ["transform-class-properties"]
},
exclude: path.resolve(__dirname, 'node_modules'),
}, {
test: /\.json$/,
loader: 'json',
},
],
},
externals: {
cherrio: 'window',
'react/lib/ExecutionEnvironment': true,
'react/lib/ReactContext': 'window',
'react/addons': true,
},
},
webpackServer: {
noInfo: true,
},
plugins: [
'karma-webpack',
'karma-jasmine',
'karma-sourcemap-loader',
'karma-phantomjs-launcher',
'karma-spec-reporter',
'karma-chrome-launcher',
],
babelPreprocessor: {
options: {
presets: ['airbnb'],
},
},
reporters: ['spec'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['PhantomJS'],
singleRun: false,
});
};
Here is my webpack config:
var path = require('path');
var webpack = require('webpack');
module.exports = {
devtool: 'inline-source-map',
entry: [
'babel-polyfill',
'webpack-hot-middleware/client',
'./src/client/index'
],
output: {
path: path.resolve(__dirname, './static/dist'),
filename: 'bundle.js',
publicPath: '/dist/'
},
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV || 'development')
}
})
],
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel',
query: {
plugins: [,
[
'react-transform', {
transforms: [{
transform: ['react-transform-hmr']
imports: ['react'],
locals: ['module']
}, {
transform: 'react-transform-catch-errors',
imports: ['react', 'redbox-react']
}]
}
]
]
},
include: [path.resolve(__dirname, 'src')]
},
{
test: /\.css?$/,
loaders: ['style', 'raw']
}
]
}
};

Resources