I use ReactJS with Webpack and TypeScript.
I'm trying to include CSS with React. But my CSS is not use by my React application.
I created a global.d.ts file to declare my css module. I imported my css into my.tsx file but when I add a class to an element, nothing works.
I have already tried to install a css module but I didn't succeed. So, I just made the solution to create a global.d.ts file
global.d.ts :
declare module '*.css';
Hello.tsx
import * as css from './Hello.css';
export interface HelloProps {
compiler: string;
framework: string;
}
export class Hello extends React.Component<HelloProps, {}> {
render() {
return (
<form>
<p className={css.test}> Test </p>
</form>
);
}
}
Hello.css
.test {
color: red;
}
webpack.config.js
module: {
rules: [
.....
{ test: /\.css$/, exclude: /node_modules/, use: ['style-loader', 'css-loader'] }
]
},
The word "test" is written in black.
When it should be in red
This would be due to you not having modules set to true in your css-loader options.
// webpack.config.js
rules: [
{
test: /.css$/,
exclude: /node_modules/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
],
Also, i would just do the following as there's no need for the * import.
import css from './Hello.css'
and then in your jsx:
<Component className={css.test} />
im quite new to react but i think if you remove:
"import * as css from './Hello.css';" And Replace it with "import './Hello.css';"
Related
I created a new React app with create-react-app (using React ver. 16.6.3). Now I want to use SCSS for my components. So first I ran the eject script. Then in webpack.config.dev.js I did the following edit:
{
test: cssRegex,
exclude: cssModuleRegex,
use: getStyleLoaders({
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}),
}
I also installed node-sass package.
Then I created my Test .scss file:
.Test {
background-color: gold;
.Header {
color: lighten(purple, 20%);
}
}
And my Test component with importing the .scss file
import React from 'react';
import style from './test.scss';
const Test = (props) => (
<div className={style.Test}>
This is div1
<div className={style.Header}>Div 2</div>
</div>
);
export default Test;
That didn't work and I didn't see any styling. I tried to import the .scss directly and use it:
import './test.scss';
...
<div className='Test'>
This is div1
<div className={style.Header}>Div 2</div>
</div>
...
That did work and I saw the styling on the div with className='Test'.
I tried to change the webpack as follows:
const CSSModuleLoader = {
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
localIdentName: '[local]__[hash:base64:5]',
minimize: true
}
}
const CSSLoader = {
loader: 'css-loader',
options: {
modules: false,
sourceMap: true,
minimize: true
}
}
const postCSSLoader = {
loader: 'postcss-loader',
options: {
ident: 'postcss',
sourceMap: true,
plugins: () => [
autoprefixer({
browsers: ['>1%', 'last 4 versions', 'Firefox ESR', 'not ie < 9']
})
]
}
}
...
{
test: /\.scss$/,
exclude: /\.module\.scss$/,
use: ['style-loader', CSSLoader, postCSSLoader, 'sass-loader']
},
{
test: /\.module\.scss$/,
use: [
'style-loader',
CSSModuleLoader,
postCSSLoader,
'sass-loader',
]
},
At first I got an autoprefixer not defined error. I imported it with const autoprefixer = require('style-loader') - that made this error disappear, though I'm still not convinced that was the correct require and correct fix.
But then I got the following error:
Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
- configuration.module.rules[2].oneOf[0].use should be one of these:
non-empty string | function | object { loader?, options?, ident?, query? } | function | [non-empty string | function | object { loader?, options?, ident?, query? }]
-> Modifiers applied to the module when rule is matched
Details:
* configuration.module.rules[2].oneOf[0].use should be a string.
* configuration.module.rules[2].oneOf[0].use should be an instance of function
* configuration.module.rules[2].oneOf[0].use should be an object.
* configuration.module.rules[2].oneOf[0].use should be an instance of function
* configuration.module.rules[2].oneOf[0].use[1] should be a string.
* configuration.module.rules[2].oneOf[0].use[1] should be an instance of function
* configuration.module.rules[2].oneOf[0].use[1] has an unknown property 'loaders'. These properties are valid:
object { loader?, options?, ident?, query? }
Don't know how to deal with that...
How do I configure webpack to either immediately compile .scss to .css in the same directory (that way I can import .css and use it regularly with style.Class) or to use the .scss import in my file in the same manner and later compile it to .css for production?
Please use below rules in webpack file and remove extra code.
rules: [
{
test: /\.s?css$/,
use: [
'style-loader',
'css-loader',
'sass-loader'
]
}
]
I am using styled-components in my project, but it just creates a style tag in the head. Is there any way to export those styles into external stylesheet?
NOTE: I am using Webpack.
You can apply the extract-text-plugin in order to extract the imports into a separate external css file.
const ExtractTextPlugin = require("extract-text-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
]
}
In my app, lets say I have two JS pages A and B, and each import a different stylesheet (import '../style/<A or B.css>').
Both stylesheets have identical classnames but but different properties.
I run yarn run dev ==> dev: webpack-dev-server --inline --hot ==> webpack -p
This is what my html <head> looks like
https://imgur.com/a/1JVb5
page A stylesheet is loaded first, then page B css style is loaded after
When I go to Page B, the css is correct
When I go to Page A, the css is mixed up and some class styles are overriden by page B.css.
My project structure is like
public/
bundle.js
index.html
src/
components/
pages/
style/
App.js
index.js
package.json
webpack.config.js
my webpack.config.js is
const path = require('path');
var config = {
entry: path.resolve(__dirname, 'src', 'index.js'),
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js'
},
devServer: {
contentBase: path.resolve(__dirname, 'src'),
publicPath: path.resolve(__dirname, 'public')
},
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: [
{ loader: 'babel-loader',
options: { presets: ['react','env'] } }
]
},
{
test: /\.css$/,
use: [
{ loader: "style-loader?singleton",
options:
{ singleton: true }
},
{ loader: "css-loader" }
]
}
]
}
};
module.exports = config;
I want Webpack to merge the multiple elements and fix the css override issue
In Webpack, I have tried style-loader?singleton and { singleton: true } but it didnt work.
EDIT 1: looking into extract-text-webpack-plugin
EDIT 2:
import movieStyle from '../style/MovieDetail.css'
...
return (
<div id="CellDetail_right" className={ movieStyle['cell-detail-right'] }>...</div>
)
Ok, I added options: { modules: true } and it didnt work. My classNames are hyphenated and after compiling the browser renders the components WITHOUT any style or classes.
Div on browser looks like <div id="CellDetail_right">...<div>
One solution is to enable local scoped css to avoid styles bleeding/overrides.
Update your css-loader options to include modules: true
{
test: /\.css$/,
use: [
{
loader: "style-loader",
options: { singleton: true }
},
{
loader: "css-loader",
options: {
modules: true,
camelCase: 'dashes',
localIdentName: '[path][name]__[local]'
}
}
]
}
Then, using in your components as:
import styles from '../style/MovieDetail.css';
function MyComponent() {
return (
<div className={styles.container}>
<div className={styles.cellDetailRight}>Some Content</div>
</div>
);
}
This ensures that despite you have more .container rules defined in other css files, this particular rule becomes to something like ._-path-to-component__container.
Using camelCase: 'dashes' in options transform your hyphenated rules.
dashes in class names will be camelized
You can also review my webpack-demo project which includes configs to handle your scenario.
Check the webpack configurations
Read more on css-loader options
I created a react app using create-react-app and everything works fine except that I can't figure out how to load css/stylus files.
In my previous react project that wasn't created using create-react-app I used webpack.config but now I don't know where to include this file and how to use it.
This is my folder structure:
.
+--client
| +--node_modules
| +--public
| +--src
| +--package.json
+--server
| +--node_modules
| +--src
| +--.babelrc
| +--package.json
This is my previous webpack.config.dev.js file:
import path from 'path';
import webpack from 'webpack';
export default {
entry: [
'webpack-hot-middleware/client?reload=true',
path.join(__dirname, '/client/index.js')
],
output: {
filename: 'bundle.js',
path: '/',
publicPath: '/'
},
plugins: [
new webpack.NoEmitOnErrorsPlugin(),
new webpack.HotModuleReplacementPlugin()
],
module: {
rules: [
{
test: /\.js$/,
include: path.join(__dirname, 'client'),
loader: 'babel-loader',
},
{
test: /\.styl$/,
use: [
'style-loader',
'css-loader',
{
loader: 'stylus-loader',
},
],
},
{
test: /\.css?$/,
use: [
'style-loader',
{
loader: 'css-loader',
},
],
},
],
},
resolve: {
extensions: [ '.js', '.styl' ]
}
}
Please let me know if I need to provide additional information.
There is detailed informations about how to add SCSS and Less files to create-react-app project on their documentation. You can check here for more detail.
You can add basic CSS styling with just importing the file like shown below;
import '/css/main.css';
Or you can add as classNames
const styles = {
header: {
fontSize: 18,
color: '#909090',
}
};
export default class Header extends React.Component {
render() {
return (
<h1 className={styles.header}>This is a header</h1>
);
}
}
One of the approaches involves loading CSS files (via css-loader) from your JS files, for a Text.jsx
import React from 'react';
import './screen.css'; // if screen.css is located next to Text.jsx
class Text extends React.Component {
// ...
}
export default Text;
You could also generate an output CSS, using e.g. ExtractTextPlugin (see Webpack2 loading and extracting LESS file)
I am attempting to change a button's style in ReactJS with the "className" element. However, I get back an error stating "Unresolved variable nameOfClass" in WebStorm, and the stylistic changes are not made when I run webpack and open the page on localhost. I have attempted different methods of importing the CSS file and naming conventions to no avail.
The file with the React Component class is here:
import * as React from "react";
var styles = require('./Roster.css');
export class Roster extends React.Component<{},{}> {
render() {
return (
<div>
<button className={styles.nameOfClass} type="button" >Players</button>
</div>
);
}
}
And the Roster.css file is here:
.nameOfClass {
background-color: #ff0000;
}
webpack.config.js
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "./dist/bundle.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
externals: ['axios'],
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{ test: /\.tsx?$/,
loader: "ts-loader"
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'),
}
],
preLoaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
plugins: [
new ExtractTextPlugin('styles.css', { allChunks: true })
],
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};
You don't have to require the styles file.
import * as React from "react";
export class Roster extends React.Component<{},{}> {
render() {
return (
<div>
<button className="nameOfClass" type="button" >Players</button>
</div>
);
}
}
and your css file:
.nameOfClass {
background-color: #ff0000;
}
Should look something like:
import * as React from "react";
export class Roster extends React.Component<{},{}> {
render() {
return <div>
<button className="nameOfClass" type="button">Players</button>
</div>
}
}
You can't require css files, only typescript/javascript files.
There's the css-modules thing, and there are some js solutions for react/css, such as Radium and reactCss.