Fail to import a module's css file - javascript

In my React project, I am using this gem for creating a dashboard: https://github.com/luqin/react-icheck
I copy pasted their first example in my code.
On the Github page, it says I should have import the css like this:
import 'icheck/skins/all.css'; // or single skin css
If I do that, I get the error:
ERROR in ./~/icheck/skins/all.css
Module parse failed: node_modules/icheck/skins/all.css Line 3: Unexpected token ILLEGAL
You may need an appropriate loader to handle this file type.
| /* iCheck plugin skins
| ----------------------------------- */
| #import url("minimal/_all.css");
| /*
| #import url("minimal/minimal.css");
If instead I do the import like this:
import 'icheck';
There is no more error, but the page doesn't have any checkbox.
So how can I do this import properly?
I also tried using style-loader so my code looks like this:
import React from 'react';
import {Checkbox, Radio} from 'react-icheck';
import 'icheck';
require("style!raw!icheck/skins/all.css");
var Criteria = React.createClass({
getInitialState: function() {
return {showGallery: false, showOtherCriteria: false};
},
toggleShowGallery: function() {
this.setState({showGallery: !this.state.showGallery});
},
toggleShowOtherCriteria: function() {
this.setState({showOtherCriteria: !this.state.showOtherCriteria});
},
render: function() {
return (
<div>
<div onClick={this.toggleShowOtherCriteria} className="btn-group" role="group" aria-label="...">
<button type="button" className="btn btn-default">Cold</button>
</div>
{style.use()}
{this.state.showOtherCriteria
?
<div onClick={this.toggleShowGallery} id="channels" className="span12">
<Checkbox
checkboxClass="icheckbox_square-blue"
increaseArea="20%"
label="Checkbox"
/>
<Checkbox
id="checkbox1"
checkboxClass="icheckbox_square-blue"
increaseArea="20%"
/>
<label for="checkbox1">First name</label>
<Radio
name="aa"
radioClass="iradio_square-blue"
increaseArea="20%"
label="Radio"
/>
</div>
:
null
}
{style.unuse()}
</div>
);
}
});
module.exports = Criteria;
However, now I get:
Module not found: Error: Cannot resolve module 'raw'
How could I use style-loader properly?

In your webpack config loader section add
module: {
loaders: [
{
test : /\.scss$/,
include : path.join(__dirname, 'sass'),
loaders : ["style", "css?sourceMap", "sass?sourceMap"]
}
]
}
By adding this code you have added three loaders namely (style,css and sass).
These three loaders perform following operations
Turn your scss files into plain CSS with the sass loader
Resolve all the imports and url(...)s in the CSS with the help of CSS loader
Insert those styles into the page with the style loader
Then require your css file from the entry point of your app e.g app.js
require('app.scss');
Edit: If you are not using sass then you don't need sass loader, also you need to change test:/\.css$/

Add webpack to your devDependencies in package.json using npm i css-loader style-loader. After that add the css-loader and style-loader to your list of loaders in webpack.config.js. Sample
module.exports = {
module: {
loaders: [{
test: /\.css?$/,
loaders: ['style', 'css']
}]
}
}
Once you have added the loaders to config, you can import your css files in you components

Related

MUI5 not working with jest - SyntaxError: Cannot use import statement outside a module

Reproducible repo: https://github.com/hutber/cannotusestatement
What is more worrying is: https://codesandbox.io/s/vigilant-bartik-bmz8x in the sandbox the tests pass. However if you checkout the above repo, which was imported into this sandbox it will not pass locally.
I have no doubt that the issue is my jest does not compile the node_modules that would be needed for running my tests. But I am at a loss now on how to get it working.
I would simply like to be able to run the tests. They do not run currently
test
import React from 'react'
import { renderWithThemeProvider, screen } from 'test-utils'
import { Select } from './Select'
it('renders correctly', () => {
const tree = renderWithThemeProvider(<Select id="testSelect"></Select>)
expect(tree).toMatchSnapshot()
})
jest.config.js
module.exports = {
roots: ['<rootDir>', './src'],
moduleDirectories: ['<rootDir>', 'node_modules/', './src'],
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
testEnvironment: 'jsdom',
testMatch: ['**/*.test.(ts|tsx)', '**/__tests__/*.(ts|tsx)'],
moduleNameMapper: {
// Mocks out all these file formats when tests are run
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': 'identity-obj-proxy',
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
'app-config': '<rootDir>/app-config/default',
'^#components(.*)$': '<rootDir>/src/components$1',
'^#themes(.*)$': '<rootDir>/src/themes$1',
},
coverageThreshold: {
global: {
statements: 50,
},
},
}
babel.config.js
module.exports = {
presets: ['#babel/preset-env', '#babel/preset-react'],
env: {
test: {
presets: ['#babel/preset-env', '#babel/preset-react'],
plugins: [
[
'babel-plugin-transform-imports',
'#babel/plugin-proposal-class-properties',
'transform-es2015-modules-commonjs',
'babel-plugin-dynamic-import-node',
'babel-plugin-styled-components',
],
},
},
}
package.json
"test": "jest --watchAll=false",
yarn test
(base) hutber#hutber:/var/www/target/component-library$ yarn test src/components/Select/Select.test.tsx
yarn run v1.22.17
$ jest --watchAll=false src/components/Select/Select.test.tsx
FAIL src/components/Select/Select.test.tsx
● Test suite failed to run
Jest encountered an unexpected token
Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.
Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.
By default "node_modules" folder is ignored by transformers.
Here's what you can do:
• If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
• If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
• To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
• If you need a custom transformation specify a "transform" option in your config.
• If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/configuration
For information about custom transformations, see:
https://jestjs.io/docs/code-transformation
Details:
/var/www/target/component-library/node_modules/#mui/material/styles/styled.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){import { createStyled, shouldForwardProp } from '#mui/system';
^^^^^^
SyntaxError: Cannot use import statement outside a module
1 | import React from 'react'
> 2 | import styled from '#mui/material/styles/styled'
| ^
3 |
4 | import MuiSelect, { SelectProps as MuiSelectProps } from '#mui/material/Select'
5 | import InputLabel from '#mui/material/InputLabel'
at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1728:14)
at Object.<anonymous> (src/components/Select/Select.tsx:2:1)
Test Suites: 1 failed, 1 total
Tests: 0 total
Snapshots: 0 total
Time: 3.272 s
import React from 'react'
import styled from '#mui/material/styles/styled'
import MuiSelect, { SelectProps as MuiSelectProps } from '#mui/material/Select'
import InputLabel from '#mui/material/InputLabel'
import MenuItem from '#mui/material/MenuItem'
import MuiFormControl from '#mui/material/FormControl'
interface ISelect extends MuiSelectProps {
id: string
label?: string
options?: { text: string; option: string }[]
}
const FormControl = styled(MuiFormControl)`
color: #fff;
border-radius: 30px;
width: 180px;
`
export const Select: React.FC<ISelect> = ({ label, id, children, options, ...props }) => {
return (
// #ts-ignore
<FormControl fullWidth hiddenLabel>
{label && (
<InputLabel id={`input_${id}`} shrink={false}>
{label}
</InputLabel>
)}
<MuiSelect id={id} {...props}>
{options && options.map(({ text, option }: { text: string; option: string }) => <MenuItem value={option}>{text}</MenuItem>)}
{children && children}
</MuiSelect>
</FormControl>
)
}
export default Select
First you have two exports in your Select.tsx file. Just use the default export, so change line 20 to:
const Select: React.FC<ISelect> = ({ label, id, children, options, ...props }) => {
Then in your Select.test.tsx file change to:
import Select from './Select'
Finally to fix the import issue change your code in Select.tsx to:
import { styled } from '#mui/material'
This is a fairly common issue as can be seen here.

CSS module is not working in react 16.13.1

I want to style components in react JS. I tried several ways to do that. When I try to create a CSS object and apply it to the component in the same JS file, then it is working. But when I try to apply CSS from external CSS file and import it in the JS file then it is not working. And I have also tried to save that file as filename.module.css. But it didn't help me.
The list of installed node modules and their versions is given below.
> #material-ui/core#4.9.11
> #material-ui/icons#4.9.1
> firebase#7.14.1
> react#16.13.1
> react-dom#16.13.1
> react-router-dom#5.1.2
> react-scripts#3.4.1
In webpack.config.js file of react-script module, I found below code:
const cssRegex = /\.css$/;
const cssModuleRegex = /\.module\.css$/;
const sassRegex = /\.(scss|sass)$/;
const sassModuleRegex = /\.module\.(scss|sass)$/;
So I guess my react project is supporting CSS files as well as SCSS and SASS files. Did I understand correctly?
header.module.css file:
.heading {
color: '#3592EF';
font-weight: '600';
letter-spacing: '2px';
}
.navButton {
color: '#444';
font-size: '16px';
padding: '4px 8px';
margin: 'auto';
margin-right: '15px';
}
Header.js file:
import React from 'react';
import { Button } from '#material-ui/core';
import styles from './header.module.css';
export default class Header extends React.Component {
render() {
return (
<div>
<span className={styles.headling}>Heading element</span>
<Button className={styles.navButton}>Home</Button>
<Button className={styles.navButton}>About</Button>
</div>
);
}
}
The output is coming with the Heading element and Home, About button. But without CSS style.
How can I solve this issue?
Thank you.
CSS module is included in react
all you have to do is building a file with the correct name like "example.module.css" and import it with the correct path if it's in the same folder `import tst from 'example.module.css' or whatever path it is in, you can replace "tst" with any any name you like.
and then you can use it in className like
<button className={tst.buttonPrimary}>Submit /button>
this video can help you more:
https://www.youtube.com/watch?v=Udf951dyTdU
Generally custom components do not accept className prop if it is not propagated to the inner of the component.
Looking in the material ui react components Button documentation, this component cannot have className property.
https://material-ui.com/components/buttons/
It means, you cannot use it. To convince your self, try to use general html <button> and it will work, you see.
Edit: grammar
first : open your terminal and run "npm install css-loader style-loader --save-dev"
These loaders enable Webpack to bundle CSS files
Second: in your webpack.config.js file, add the new loaders for interpreting CSS files:
module.exports = {
...
module: {
rules: [
...
*///
{
test: /\.css$/i,
exclude: /node_modules/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
modules: true,
},
},
],
},
*////
],
},
...
};

Importing SVG in NextJS

I am trying to import an svg within a NextJS project, everytime I get this error
./assets/aboutimg.svg 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="578" height="1028" viewBox="0 0 578 1028">
| <image id="_64538565_2370063099695596_8091233071539421184_n" data-name="64538565_2370063099695596_8091233071539421184_n" width="578" height="1028" xlink:href="
I have tried using next-images and also svgr. I will paste my About.js code below, it would be excellent if someone could let me know what I have been doing wrong.
import LayoutNoLogo from '../comps/LayoutNoLogo'
import AboutImg from '../assets/aboutimg.svg'
const About = () => {
return (
<LayoutNoLogo>
<div className="row">
<div className="column-1">
<img src={AboutImg} />
</div>
<div className="column-2">
<h1>About</h1>
</div>
</div>
<style jsx>{`
`}</style>
</LayoutNoLogo>
)
}
export default About;
I've finally used file-loader for using SVG images in my project.
install webpack and file loader : yarn add webpack, yarn add file-loader -D
in next.config.js:
module.exports = {
//...other configs
webpack: (config, {}) => {
config.module.rules.push({
test: [/\.svg$/, /\.woff$/],
loader: 'file-loader',
options: {
name: '[name].[hash:8].[ext]',
publicPath: `/_next/static/images/`, //specify the base path
outputPath: 'static/images', //and output path
}
})
}
}
Now I can use import img from '../assets/image.svg'
Using next-images and adding the correct module exports allowed me to use images of all file types.
https://www.npmjs.com/package/next-images

Is there's a way of importing files I serve through express.static? [duplicate]

I am wondering how to set up an inline svg with webpack?
I am following the react-webpack-cookbook.
I have my webpack.config set up correctly with the file loader.
However the example shows using a background image like this:
.icon {
background-image: url(./logo.svg);
}
which works fine, but I want to have an inline svg image how do I do this to include my logo.svg inline in my react component?
import React, { Component } from 'react'
class Header extends Component {
render() {
return (
<div className='header'>
<img src={'./logo.svg'} />
</div>
);
}
};
export default Header
Actually Michelle's answer pointed me in the right direction, and that works nicely for loading an svg file with webpack and using it as your <img> src
However to actually get the inline svg, I needed to do the following:
Instead of file-loader use svg-inline-loader as your svg loader:
{ test: /\.svg$/, loader: 'svg-inline-loader' }
Then to load the svg inline in a component:
import React, { Component } from 'react'
import logo from "./logo.svg";
class Header extends Component {
render() {
return (
<div className='header'>
<span dangerouslySetInnerHTML={{__html: logo}} />
</div>
);
}
};
export default Header
It looks like there is an inline svg wrapper for react svg-inline-react which would be another option instead of the <div dangerouslySetInnerHTML={{__html: mySvg}} />
Here is a simple non-react solution.
Install Svg inline loader
In webpack.config.js add { test: /\.svg$/, loader: 'svg-inline-loader' }
In your js file import svg image and add it to a DOM element like so
import Svg from './svg.svg';
function component() {
const element = document.createElement('div');
element.innerHTML = Svg;
return element;
}
document.body.appendChild(component());
I hope my late answer will still be useful for someone, because I don't like any of abovementioned options.
The react-svg-loader webpack loader allows you to import SVG icons like JSX components:
import Logo from './logo.svg';
class App extends Component {
render() {
return (
<div className="App">
<Logo fill="red" className="logo" width={50} height={50} />
</div>
);
}
}
and minimum config looks like this:
{
test: /\.svg$/,
use: [
{
loader: "babel-loader"
},
{
loader: "react-svg-loader",
options: {
jsx: true // true outputs JSX tags
}
}
]
}
The best part is that it just outputs the svg file contents, without any extra wrappers and dangerouslySetInnerHTML in your code.
Old question, but I didn't see this solution anywhere so I decided to post it, hoping it will help someone.
If you want to be able to style those SVG icons, you might want to load them with the raw loader:
webpack.config.js:
{
test: /\.svg$/,
loader: 'raw-loader'
}
The import in my view:
import closeIcon from 'svg/ic_close_black_24px.svg';
The template (Mustache uses 3 brackets to insert the SVG data (URL)unencoded):
<button id="closeModal">
{{{closeIcon}}}
</button>
this way the SVG data will be inserted instead of the brackets and look like this:
<button id="closeModal">
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
</button>
I'm using Backbone with Mustache template engine with Webpack 2.5.1
If I'm not mistaken, since you're using the file loader, you can utilize it in much the same way as any other require. Webpack will turn require("./logo.svg") into a path to a file, which it will emit when it bundles.
import React, { Component } from 'react'
import mySvg from './logo.svg'
class Header extends Component {
render() {
return (
<div className='header'>
<img src={mySvg} />
</div>
);
}
};
export default Header
Similar to another answer using React, there is also a handy Vue plugin as well.
vue-svg-loader just throw it in your configuration and start using. The nice thing is it will also run your svg through SVGO to optimize it.
Configuration
{
test: /\.svg$/,
loader: 'vue-svg-loader', // `vue-svg` for webpack 1.x
options: {
// optional [svgo](https://github.com/svg/svgo) options
svgo: {
plugins: [
{removeDoctype: true},
{removeComments: true}
]
}
}
}
Usage
<template>
<nav id="menu">
<a href="...">
<SomeIcon class="icon" />
Some page
</a>
</nav>
</template>
<script>
import SomeIcon from './assets/some-icon.svg';
export default {
name: 'menu',
components: {
SomeIcon,
},
};
</script>
Angular Solution (2019): Use svg-sprite-loader to combine SVGs into a single sprite that's lazy-loaded with your Webpack bundles.
Webpack
{
test: /\.svg$/,
use: [
'svg-sprite-loader',
'svgo-loader' // Optimize SVGs (optional)
]
}
HTML
<svg>
<use xlink:href="#arrow"/>
</svg>
Angular Component
export * from 'assets/images/icons/arrow.svg';
I use export (instead of import) to prevent the AOT compiler from removing the import during tree-shaking, while allowing for minimal code in the component, but you can use import if you prefer.
To use export in this way, you must configure the compiler to expect side effects from SVG files in package.json (i.e. you can not use "sideEffects": false). See the Webpack Tree Shaking Guide
"sideEffects": [
"*.svg",
],
#svgr/webpack (npm) is the inline svg loader that create-react-app uses.
Add the rule to your webpack config:
{
test: /\.svg$/,
use: ['#svgr/webpack'],
}
Then you can import svgs as React components:
import Star from './star.svg'
const App = () => (
<div>
<Star />
</div>
)
Folks who use svg-inline-loader and who stuck with "Cannot find module" error try to install babel-plugin-inline-react-svg and add it to the babel plugins:
"plugins": [
...
["inline-react-svg", {}]
],
...

how to set up an inline svg with webpack

I am wondering how to set up an inline svg with webpack?
I am following the react-webpack-cookbook.
I have my webpack.config set up correctly with the file loader.
However the example shows using a background image like this:
.icon {
background-image: url(./logo.svg);
}
which works fine, but I want to have an inline svg image how do I do this to include my logo.svg inline in my react component?
import React, { Component } from 'react'
class Header extends Component {
render() {
return (
<div className='header'>
<img src={'./logo.svg'} />
</div>
);
}
};
export default Header
Actually Michelle's answer pointed me in the right direction, and that works nicely for loading an svg file with webpack and using it as your <img> src
However to actually get the inline svg, I needed to do the following:
Instead of file-loader use svg-inline-loader as your svg loader:
{ test: /\.svg$/, loader: 'svg-inline-loader' }
Then to load the svg inline in a component:
import React, { Component } from 'react'
import logo from "./logo.svg";
class Header extends Component {
render() {
return (
<div className='header'>
<span dangerouslySetInnerHTML={{__html: logo}} />
</div>
);
}
};
export default Header
It looks like there is an inline svg wrapper for react svg-inline-react which would be another option instead of the <div dangerouslySetInnerHTML={{__html: mySvg}} />
Here is a simple non-react solution.
Install Svg inline loader
In webpack.config.js add { test: /\.svg$/, loader: 'svg-inline-loader' }
In your js file import svg image and add it to a DOM element like so
import Svg from './svg.svg';
function component() {
const element = document.createElement('div');
element.innerHTML = Svg;
return element;
}
document.body.appendChild(component());
I hope my late answer will still be useful for someone, because I don't like any of abovementioned options.
The react-svg-loader webpack loader allows you to import SVG icons like JSX components:
import Logo from './logo.svg';
class App extends Component {
render() {
return (
<div className="App">
<Logo fill="red" className="logo" width={50} height={50} />
</div>
);
}
}
and minimum config looks like this:
{
test: /\.svg$/,
use: [
{
loader: "babel-loader"
},
{
loader: "react-svg-loader",
options: {
jsx: true // true outputs JSX tags
}
}
]
}
The best part is that it just outputs the svg file contents, without any extra wrappers and dangerouslySetInnerHTML in your code.
Old question, but I didn't see this solution anywhere so I decided to post it, hoping it will help someone.
If you want to be able to style those SVG icons, you might want to load them with the raw loader:
webpack.config.js:
{
test: /\.svg$/,
loader: 'raw-loader'
}
The import in my view:
import closeIcon from 'svg/ic_close_black_24px.svg';
The template (Mustache uses 3 brackets to insert the SVG data (URL)unencoded):
<button id="closeModal">
{{{closeIcon}}}
</button>
this way the SVG data will be inserted instead of the brackets and look like this:
<button id="closeModal">
<svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path>
<path d="M0 0h24v24H0z" fill="none"></path>
</svg>
</button>
I'm using Backbone with Mustache template engine with Webpack 2.5.1
If I'm not mistaken, since you're using the file loader, you can utilize it in much the same way as any other require. Webpack will turn require("./logo.svg") into a path to a file, which it will emit when it bundles.
import React, { Component } from 'react'
import mySvg from './logo.svg'
class Header extends Component {
render() {
return (
<div className='header'>
<img src={mySvg} />
</div>
);
}
};
export default Header
Similar to another answer using React, there is also a handy Vue plugin as well.
vue-svg-loader just throw it in your configuration and start using. The nice thing is it will also run your svg through SVGO to optimize it.
Configuration
{
test: /\.svg$/,
loader: 'vue-svg-loader', // `vue-svg` for webpack 1.x
options: {
// optional [svgo](https://github.com/svg/svgo) options
svgo: {
plugins: [
{removeDoctype: true},
{removeComments: true}
]
}
}
}
Usage
<template>
<nav id="menu">
<a href="...">
<SomeIcon class="icon" />
Some page
</a>
</nav>
</template>
<script>
import SomeIcon from './assets/some-icon.svg';
export default {
name: 'menu',
components: {
SomeIcon,
},
};
</script>
Angular Solution (2019): Use svg-sprite-loader to combine SVGs into a single sprite that's lazy-loaded with your Webpack bundles.
Webpack
{
test: /\.svg$/,
use: [
'svg-sprite-loader',
'svgo-loader' // Optimize SVGs (optional)
]
}
HTML
<svg>
<use xlink:href="#arrow"/>
</svg>
Angular Component
export * from 'assets/images/icons/arrow.svg';
I use export (instead of import) to prevent the AOT compiler from removing the import during tree-shaking, while allowing for minimal code in the component, but you can use import if you prefer.
To use export in this way, you must configure the compiler to expect side effects from SVG files in package.json (i.e. you can not use "sideEffects": false). See the Webpack Tree Shaking Guide
"sideEffects": [
"*.svg",
],
#svgr/webpack (npm) is the inline svg loader that create-react-app uses.
Add the rule to your webpack config:
{
test: /\.svg$/,
use: ['#svgr/webpack'],
}
Then you can import svgs as React components:
import Star from './star.svg'
const App = () => (
<div>
<Star />
</div>
)
Folks who use svg-inline-loader and who stuck with "Cannot find module" error try to install babel-plugin-inline-react-svg and add it to the babel plugins:
"plugins": [
...
["inline-react-svg", {}]
],
...

Categories