I have sample react app and using scss. I have 2 scss file:
Colour palette:
$_color-base-white: #FFF;
$_color-base-black: #000;
$_color-base-grey: #DCDCDC;
$_color-base-charcoal: #404040;
$_color-base-turquoise: #50E3C2;
$_color-base-red: #e3454f;
$_color-base-blue: #006DEF;
$_color-base-green: #009d2f;
$palettes: (
white: (
x-light: lighten($_color-base-white, 60%),
light: lighten($_color-base-white, 40%),
mid-light: lighten($_color-base-white, 10%),
base: $_color-base-white,
mid-dark: darken($_color-base-white, 10%),
dark: darken($_color-base-white, 40%),
x-dark: darken($_color-base-white, 60%)
)
);
#function palette($palette, $tone: 'base') {
#return map-get(map-get($palettes, $palette), $tone);
}
And then I have App.scss file inside React Component:
#import '../../assets/styles/colour_semantics';
.app-header {
color: $palettes(white, mid-light);
}
And App component looks like this:
import React, { Component } from 'react';
import './App.scss';
class App extends Component {
render() {
return (
<div className="app">
<h1 class="app-header">Hello World</h1>
</div>
);
}
}
export default App;
When using only defined colours like $_color-base-white in App scss everything is ok and working but when want to use $palettes:
index.js??ref--5-1!./node_modules/sass-loader/lib/loader.js??ref--5-2!./src/containers/App/App.scss:1 Uncaught Error: Module build failed:
$palettes: (
^
(white: (x-light: white,
Why can I not use functions? Webpack plugin config looks like this:
{
test: /\.(sass|scss)$/,
use: [{
loader: "style-loader"
}, {
loader: "css-loader", options: {
sourceMap: true,
importLoaders: 2
},
}, {
loader: "sass-loader" , options: {
sourceMap: true
},
}]
},
You are calling the list and not the function.
.app-header {
color: $palettes(white, mid-light);
}
Should be
.app-header {
color: palette(white, mid-light);
}
Related
I'm building a component library to sit alongside some react apps within a monorepo, library is currently being consumed by app1 and displaying components exported from the library just fine.
The library is based on masterial ui and themed. I'm using storybook and rollup for documentation and bundling, which means having to cater to both webpack (for storybook) and rollup for the actual library build.
.storybook/main.js:
module.exports = {
stories: ['../src/**/**/*.stories.mdx', '../src/**/**/*.stories.tsx'],
addons: [
'#storybook/addon-links',
'#storybook/addon-essentials',
'storybook-addon-designs'
],
webpackFinal: (config) => {
// Default rule for images /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/
const fileLoaderRule = config.module.rules.find(
(rule) => rule.test && rule.test.test('.svg')
)
fileLoaderRule.exclude = /\.svg$/
config.module.rules.push(
{
test: /\.svg$/,
enforce: 'pre',
loader: require.resolve('#svgr/webpack')
},
{
test: /\.(woff|woff2|eot)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: require.resolve('file-loader'),
options: {
// Limit at 50k. Above that it emits separate files
limit: 50000,
// Output below fonts directory
name: '[name].[ext]',
outputPath: '../src/build/fonts/'
}
}
]
}
)
return config
}
}
And my rollup.config.js:
import commonjs from '#rollup/plugin-commonjs'
import resolve from '#rollup/plugin-node-resolve'
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import typescript from 'rollup-plugin-typescript2'
import svgImport from 'rollup-plugin-svg-hyperscript'
import url from '#rollup/plugin-url'
import packageJson from './package.json'
export default {
input: './src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true
}
],
plugins: [
peerDepsExternal(),
resolve(),
commonjs(),
typescript(),
svgImport(),
url({
include: ['**/*.woff', '**/*.eot'],
name: '[name].[ext]'
})
]
}
It should be noted that I have an Icon component that works with SVGS being bundled with rollup and displaying in storybook perfectly.
Font index:
import soehneWebKraftigWoff from './soehneWebKraftig.woff'
import soehneWebKraftigEot from './soehneWebKraftig.eot'
import soehneWebLeichtWoff from './soehneWebLeicht.woff'
import soehneWebLeichtEot from './soehneWebLeicht.eot'
export const fonts = {
soehneWebKraftigWoff,
soehneWebKraftigEot,
soehneWebLeichtEot,
soehneWebLeichtWoff
}
MuiCssBaseline:
import { fonts } from '../../fonts'
export const soehneWebKraftig = {
fontFamily: 'SoehneWebKraftig',
fontStyle: 'normal',
fontWeight: 400,
src: `url(${fonts.soehneWebKraftigWoff}) format('woff')`
}
export const MuiCssBaseline = {
'#global': {
'#font-face': [soehneWebKraftig]
}
}
The override is being indexed and exported from a folder called 'overrides' so this is my theme file:
import { createTheme } from '../../themeUtility'
import { rootPalette } from './rootPalette'
import { rootTypography } from './rootTypography'
import * as overrides from './overrides'
export const rootTheme = createTheme({
palette: rootPalette,
typography: rootTypography,
overrides: {
...overrides
}
})
The font is not loaded correctly in either storybook or in the rollup bundle (I can't see the font displaying correctly in app1 which consumes the bundle). I can see my font files renamed with hashes appearing in the rollup build output directory.
Any ideas?
Edit:
Fonts within build (but not inside the fonts folder?)
I searched for similar problems a lot but couldn't come up with a solution.
I integrated React.js with my working project. I am using Webpack.
Everything runs properly except styling.
I have Style.scss and I import this file in my react file. It compiles without an error but the actual style is not applying to the element.
The inline style works and other classes that are included normally also are fine.
Style.scss
.wtf {
font-weight: bold;
font-size: 40px;
}
Test.js
import React from 'react';
import '../Styles/Style.scss';
const style = {
border: 'solid 5px green'
};
export default class Test extends React.Component {
render() {
return (
<div style={style} className='wtf text-danger'>
Am I React.Component? And I am working too?
</div>
);
};
}
According to the snippet above, text-danger applies color red and border:solid 5px green works too, however, the style is specified in Style.scss is not working.
I checked compiled file and it seems like my scss style code exists there
This is the result in the browser
My webpack.config.js file content is below:
const path = require( 'path' );
module.exports = {
mode: 'development',
entry: {
rooms: './react-src/rooms/rooms.js',
tasks: './react-src/tasks/tasks.js'
},
output: {
filename: '[name].js',
path: path.resolve('../htdocs/react-dist')
},
module: {
rules: [
{
test: /\.scss$/,
use: [
// style-loader
{ loader: 'style-loader' },
// css-loader
{
loader: 'css-loader',
options: {
modules: true
}
},
// sass-loader
{ loader: 'sass-loader' }
]
},
{
test: /.jsx?$/,
loader: 'babel-loader',
exclude: /node_modules/,
query: {
presets: ['es2015', 'react']
}
}
]
}
};
Any idea what is the problem?
Solved
According to my example and my Webpack configuration, it was compiling styles so generating a new class name.
So, that huge token highlighted above is my actual class name which I have to use.
It can be imported as an Object so I can access class name as a property.
This is how it worked.
import React from 'react';
import style from '../Styles/Style.scss';
export default class Test extends React.Component {
render() {
return (
<div className={style.wtf}>
Am I React.Component? And I am working too?
</div>
);
};
}
if you modify your webpack config to:
{...
loader: 'css-loader',
options: {
modules: false
},
...}
you can use regular className property
Here is the error I receive:
Uncaught Error: Module parse failed: Unexpected token (15:5)
You may need an appropriate loader to handle this file type.
| /* stylelint-disable at-rule-no-unknown */
| html,
> body {
| width: 100%;
| height: 100%;
at eval (antd.css:1)
at Object../node_modules/antd/dist/antd.css (index.js:228)
at __webpack_require__ (index.js:20)
at eval (App.js:10)
at Module../KQShopping/frontend/src/App.js (index.js:97)
at __webpack_require__ (index.js:20)
at eval (index.js:2)
at Module../KQShopping/frontend/src/index.js (index.js:109)
at __webpack_require__ (index.js:20)
at index.js:84
webpack config file:
const path = require('path');
const fs = require('fs');
const lessToJs = require('less-vars-to-js');
const themeVariables = lessToJs(fs.readFileSync(path.join(__dirname, './ant-theme-vars.less'), 'utf8'));
module.exports = {
module: {
rules: [
{
loader: 'babel-loader',
test: /\.(js|jsx)$/,
exclude: /node_modules/,
options: {
plugins: [
['import', { libraryName: "antd", style: true }]
]
},
},
{
test: /\.less$/,
use: [
{loader: "style-loader"},
{loader: "css-loader"},
{loader: "less-loader",
options: {
modifyVars: themeVariables
}
}
]
}
]
}
};
App.js:
import React from "react";
import ReactDOM from "react-dom";
import { DatePicker, message } from "antd";
import "antd/dist/antd.css";
class App extends React.Component {
state = {
date: null,
};
handleChange = date => {
message.info(`Selected Date: ${date ? date.format("YYYY-MM-DD") : "None"}`);
this.setState({ date });
};
render() {
const { date } = this.state;
return (
<div style={{ width: 400, margin: "100px auto" }}>
<DatePicker onChange={this.handleChange} />
<div style={{ marginTop: 20 }}>
Selected Date: {date ? date.format("YYYY-MM-DD") : "None"}
</div>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
Babel config file:
{
"presets": ["#babel/preset-env", "#babel/preset-react"],
"plugins": ["transform-class-properties", ["import", { "libraryName": "antd", "style": "true" }]]
}
I followed multi tutorials and how-tos but I end up with an error every time and I have no idea how to fix this error since I have just started learning about babel and webpack with small experince.
In this problem I followed exactly this docs https://ant.design/docs/react/getting-started and I still end up with an error
In the end, I used CSS, in the webpack config file add this:
{
use: ['style-loader', 'css-loader'],
test: /\.css$/
}
You shouldn't need to import the antd css at the top of App.js. I also think that the babel plugin should have style set to css in the babel config file (that's how our config file is set up anyway!).
[
'import',
{
'libraryName': 'antd',
'style': 'css'
}
]
Our less loader also has javascriptEnabled set to true:
test: /\.less$/,
use: [{
loader: 'style-loader' // creates style nodes from JS strings
},
{
loader: 'css-loader' // translates CSS into CommonJ
},
{
loader: 'less-loader', // compiles Less to CSS
options: {
javascriptEnabled: true
}
}]
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?
Not sure what I'm doing wrong here, where I console.log(style) it is just a blank object but defined. No errors.
Login.js - component
import React, {Component} from 'react';
import {connect} from 'react-redux';
import PropTypes from 'prop-types';
import CSSModules from 'react-css-modules';
import { Row, Col } from 'antd';
import styles from './Login.css';
import Logo from '../../components/Logo/Logo';
class Login extends Component {
constructor (props) {
super(props);
}
render () {
const {dispatch} = this.props
console.log(styles);
return (
<Row type="flex" justify="space-around" align="middle" className="container">
<Col sm={16} md={16} lg={9}>
<div className={styles.content}>
<h1>Sign In</h1>
<Logo size="large" className="logo" />
</div>
</Col>
</Row>
)
}
}
Login.propTypes = {
data: PropTypes.object,
history: PropTypes.object,
dispatch: PropTypes.func
}
function select (state) {
return {
data: state
}
}
export default connect(select)(CSSModules(Login, styles));
Login.css - nothing special going on here
body {
background-color: #f0f0f0;
}
.container {
width: 100vw;
height: 100vh;
}
.content {
position: relative;
background-color: #ffffff;
padding: 30px 20px 20px 20px;
}
and the webpack.config.js most likely the culprit but I can't seem to figure out the issue
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'index.html',
inject: 'body'
})
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve('dist'),
filename: 'index_bundle.js'
},
devServer: {
historyApiFallback: true,
},
mode: "development",
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
}, {
test: /\.js$/,
exclude: /node_modules/,
use: "babel-loader"
}, {
test: /\.jsx?$/,
exclude: /node_modules/,
use: "babel-loader"
}
]
},
plugins: [
HtmlWebpackPluginConfig,
new ExtractTextPlugin({filename: 'style.css'})
]
}
The app compiles and runs fine just the react-css-module isn't namespacing the styles and the styles aren't being applied to the element.
Its seems you are missing in css-loader:
modules: true to enable CSSModules spec for css-loader.
Check the doc.
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader?modules"
}
I had the same problem .it start to work after I add
modules=true
in the webpack.config.js
as follows.
module:{
rules:
[
{
test:/\.css$/,
loader:'style-loader!css-loader?modules=true'
}
]
}