I am using webpack to build svg-sprite.
But there is a problem: part of icons have multiple colors, and part — only one. They are used as is.
One color icons should change color according to :hover / :active.
And, according to this I should clean fill attributes for one color icons.
Which I can't do with multicolor ones.
I decide to separate them to different folders and create two webpack rules:
{
test: /icon\/.*\.svg$/,
loaders: [
'svg-sprite-loader',
{
loader: 'svgo-loader',
options: {
plugins: [
// ...
],
},
},
],
},
{
test: /monoicon\/.*\.svg$/,
loaders: [
'svg-sprite-loader',
{
loader: 'svgo-loader',
options: {
enforce: 'pre',
plugins: [
// ...
{ removeAttrs: { attrs: '(fill|stroke)' } },
],
},
},
],
},
And everything is fine, but it don't actually work. I am getting in the console:
…/monoicon/cross.svg
Module build failed: Error: Error in parsing SVG: Non-whitespace before first tag.
Line: 0
Column: 1
Char: i…
Digging the web I have found:
It was a problem with the way I was loading it. you need to prefix require("-!... when you're overriding other loaders...
https://github.com/jhamlet/svg-react-loader/issues/3#issuecomment-146334228
So it look like source of the problem is that I have to rules with svgo-loader. Rewrite webpack loaders rule in each svg import — kinda shitty idea. So how I may solve this in appropriate way?
Regards.
I am an idiot. Write regexp's:
/\/icon\/.*\.svg$/
/\/monoicon\/.*\.svg$/
Related
I am a very new to programming. So read a few articles and trying to configure web-pack for the following purpose.
I'm building a preact widget and the CSS is clashing with parent website. Hence I'm trying to create a shadow DOM and then load css into shadow DOM instead of adding into the document header.
I have created a shadow DOM and I have configured webpack to inject styles into the shadow root like below.
rules: [
// packs SVG's discovered in url() into bundle
{ test: /\.svg/, use: 'svg-url-loader' },
{
test: /\.css$/i,
use: [
{
loader: require.resolve('style-loader'),
options: {
insertInto: function () {
return document.getElementById('#widget-_hw').shadowRoot;
},
},
},
{
// allows import CSS as modules
loader: 'css-loader',
options: {
modules: {
// css class names format
localIdentName: '[name]-[local]-[hash:base64:5]'
},
sourceMap: isDevBuild
}
}
]
But I'm getting the following error
Module build failed (from ./node_modules/style-loader/dist/cjs.js):
ValidationError: Invalid options object. Style Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'insertInto'. These properties are valid:
object { injectType?, attributes?, insert?, base?, esModule? }
The error tells you exactly what's wrong: insertInto is not a valid option on style-loader.
insert, which the error message tells you is one of the valid options, is likely what you want.
I really like the separation of className and styleName that babel-plugin-react-css-modules offers for global and local styles respectively, but have had some trouble getting the plugin to work with create-react-app.
I've tried installing the plugin by running
npm install babel-plugin-react-css-modules --save
... as it says to do in the project (github https://github.com/gajus/babel-plugin-react-css-modules#css-modules) ...
... and have also used craco as suggested in a similar thread (#5113) to help overcome the limitations of create-react-app without the need to eject, but am still unable to import a scss file and reference to it using styleName.
Does anyone know if I'm missing something else here? Sorry if it's a noob question, I'm new to React and have been looking for a solution to this for a while now.
1. add the plugin to .babelrc first.
"plugins": [
["babel-plugin-react-css-modules",
{
"webpackHotModuleReloading": true,
"autoResolveMultipleImports": true
}],....
]
2. add css rule in webpack.config.js.
below is my configuration that you can reference from.
make sure that
2.1 option modules set to true.
2.2 localIdentName follow this format. localIdentName: "[path]___[name]__[local]___[hash:base64:5]"
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /(node_modules|bower_components)/,
use: [
{
loader: "babel-loader",
options: { cacheDirectory: true }
}
]
},
{
test: /\.css$/i,
use: [
{
loader: ExtractCssChunks.loader,
options: { hot: true }
},
{
loader: "css-loader", //generating unique classname
options: {
importLoaders: 1, // if specifying more loaders
modules: true,
sourceMap: false,
localIdentName: "[path]___[name]__[local]___[hash:base64:5]" //babel-plugin-css-module format
//localIdentName: "[path][name]__[local]" //recommended settings by cssloader#local-scope , this option generate unique classname for compiled css
}
}
]
},
I am trying to include another library's css for their component in my own application. For reference, I am trying to use this data table library: https://github.com/filipdanic/spicy-datatable.
In the docs, it states Out of the box, spicy-datatable is bare-bones. Include this CSS starter file in your project to get the look from the demo. Edit it to suit your needs.
I tried to import the style sheet at the top of the component that I am building like this: import * as spicy from 'spicy-datatable/src/sample-styles.css'; in my own component file. It was not styled. I tried putting the raw code into my index.scss file in my assets/styles folder - did not work. I tried putting it in my own styles file ./component.scss - did not work.
I have them currently set up like:
import * as styles from './component.scss';
import * as spicy from 'spicy-datatable/src/sample-styles.css';
and am getting an error:
Module parse failed: Unexpected token (4:0)
You may need an appropriate loader to handle this file type.
webpack.config.js
const dirNode = 'node_modules';
const dirApp = path.join(__dirname, 'client');
const dirAssets = path.join(__dirname, 'assets');
/**
* Webpack Configuration
*/
module.exports = {
entry: {
vendor: ['lodash'],
bundle: path.join(dirApp, 'index')
},
resolve: {
modules: [dirNode, dirApp, dirAssets]
},
plugins: [],
module: {
rules: [
// BABEL
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /(node_modules)/,
options: {
compact: true
}
},
// CSS / SASS
{
test: /\.(scss)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
}
},
'sass-loader'
]
},
// IMAGES
{
test: /\.(jpe?g|png|gif)$/,
loader: 'file-loader',
options: {
name: '[path][name].[ext]'
}
}
]
}
};
.babelrc
"plugins": [
[
"react-css-modules",
{
"filetypes": {
".scss": {
"syntax": "postcss-scss"
}
},
"webpackHotModuleReloading": true
}
]
I'm not sure if I need to add something to specifically handle .css files, this is my first time working with CSS Modules. I thought react-css-modules did that so I'm not quite sure why the CSS file isn't loading correctly.
Edit:
Edited my webpack around to include CSS:
{
test: /\.(css)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
}
}
]
},
Error is gone, but styles still do not appear.
Could you try changing below:
import * as spicy from 'spicy-datatable/src/sample-styles.css';
to
import from 'spicy-datatable/src/sample-styles.css';
If you are using CSS-Modules, try below:
import spicy from 'spicy-datatable/src/sample-styles.css';
and then use the style on JSX element like below:
<h1 className={classes.<className in CSS here>}>
I setup a codesandbox with the spicy-datatable library and imported the styles and looks like it applied. The styles are in "Hello.css" file and it is imported in "index.js".
https://codesandbox.io/s/4j31xj3689
If library doesn't use css-modules (uses className attribute instead of styleName) we need to disable modules for imported css, so the class names will remain unchanged. This can be done in 2 ways:
Modify your Webpack config
module: {
rules: [
{
test: /\.(css)$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: false
}
}
]
},
...
]
}
Import library css directly into your scss stylesheet (thanks to this answer pointing out how to perform proper .css import). Make sure to exclude .css file extension from import line. :global directive will prevent css-modules to modify class names for all styles within this directive.
:global {
#import "~library-module-name/.../CssFileWithoutExtension";
}
Issue
I am trying to use babel-plugin-react-css-modules in my React project for better performance as opposed to React CSS Modules.
However, the styles are being not applied correctly.
Cause
The version in <style> tag is wrapped with weird hypen, for example:
In the <style> tag: -components-Foo-___Foo__foo___1fcIZ-
On the DOM
element class name: components-Foo-___Foo__foo___1fcIZ
Even if we are using the same localIdentName, the generated results
are different from selectors in css and className on DOM element.
(Note: In babel-plugin-react-css-modules, the localIdentName is
[path]___[name]__[local]___[hash:base64:5] as hard-coded in
options.generateScopedName)
Any idea why there is a hypen-wrapper?
Found the solution myself after some struggling.
Cause
This is due to a quirk of css-loader: if there are double quotes around localIdentName option, it will wrap the generated class name with hyphens.
Working Examples
So instead of doing this in webpack config:
{
test: /\.(scss|sass)$/,
use: [
'style-loader?sourceMap',
'css-loader?modules="true"&importLoaders="1"&localIdentName="[path]___[name]__[local]___[hash:base64:5]"',
'sass-loader?sourceMap',
],
},
Do this:
{
test: /\.(scss|sass)$/,
use: [
'style-loader?sourceMap',
'css-loader?modules="true"&importLoaders="1"&localIdentName=[path]___[name]__[local]___[hash:base64:5]',
'sass-loader?sourceMap',
],
},
Or event better if you are using Webpack 2+
{
test: /\.(scss|sass$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
sourceMap: true,
localIdentName: '[path]___[name]__[local]___[hash:base64:5]'
}
},
'sass-loader'
]
}
I am trying to setup my react project so I can use SASS in the SCSS format.
This is in my webpack.config.dev.js:
{
test: /\.scss$/,
exclude: /node_modules/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('sass-loader'),
}
]
}
I import the scss files into my jsx in two different ways:
import './index.scss';
import css from './ModalWrapper.scss';
When I run the app I am currently getting the error:
./src/index.scss
Module build failed:
body {
^
Invalid CSS after "m": expected 1 selector or at-rule, was "module.exports = __"
in /pathtoapp/web/src/index.scss (line 1, column 1)
It appears me, that one, react is trying to interpret the SCSS as CSS which should work. In addition, react believes that body is not valid CSS. There, I would believe that neither CSS or SCSS are being loaded correctly.
Any help would be appreciated. There are quite a few unanswered questions to this problem.
If you are on Webpack 3, add this to module.rules
{
test: /\.scss$/,
loader: [
require.resolve('style-loader'),
require.resolve('css-loader'),
require.resolve('sass-loader'),
]
},
And then add the file loader and make sure to add .scss to the array of the key exclude like this
{
loader: require.resolve('file-loader'),
// Exclude `js` files to keep "css" loader working as it injects
// it's runtime that would otherwise processed through "file" loader.
// Also exclude `html` and `json` extensions so they get processed
// by webpacks internal loaders.
exclude: [/\.js$/, /\.html$/, /\.json$/, /\.scss$/,],
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
}
And of course, make sure you have style-loader, sass-loader, css-loader and file-loader in you package.json. This code snippet worked for me when using the latest version of create-react-app.
This is what ended up working for me:
{
test: /\.scss$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader',
options: {
modules: true,
sourceMap: true,
localIdentName: "[local]___[hash:base64:5]",
},
}, {
loader: 'sass-loader',
options: {
outputStyle: "expanded",
sourceMap: true,
},
}]
},
I'm sure the other answers are just as good, but for maximum brevity, this works for me (I erased some of the internal webpack.config.dev.js comments presumably made by the create react folks):
module: {
strictExportPresence: true,
rules: [
{
test: /\.scss/,
use: ['style-loader','css-loader', 'sass-loader']
},...
I don't know if it matters, but I put this on the top. Also, yes, make sure to add the scss file to the excluded array as mentioned above.