CSS Modules cannot be imported from within node_modules - reactjs

I am using one library in my main project. The library code looks like this /node_modules/#myCompany/all_components/src/Footer/components/Navlink/index.js
import React from 'react';
import styles from './style.module.scss';
export const NavLinks = ({ linksList }) => (
linksList
.map(({ url, title, id }) => (
<a
key={id}
className={styles.navLink}
href={url}>
{title}
</a>
))
);
Now in Next app /pages/index.js
import {NavLinks} from '#myCompany/all_components';
.....
export const Home = ({ data }) => {
return ()
};
.bablerc
{
"presets": ["next/babel"]
}
next.config.js
module.exports = {
webpack: (config) => {
config.resolve.extensions = ['.js', '.jsx'];
config.module.rules.push(
{test: /\.(js|jsx)$/, use: {
loader: "babel-loader",
options: {
presets: ['#babel/preset-env', '#babel/preset-react']
}
}}
);
return config;
}
}
But I am getting error -
error - ./node_modules/#myCompany/all_componentss/src/Footer/components/NavLinks /style.module.scss
CSS Modules cannot be imported from within node_modules.
Read more: https://nextjs.org/docs/messages/css-modules-npm
Location: node_modules\#myCompany/all_components\src\Footer\components\NavLinks\index.js
[BABEL] Note: The code generator has deoptimised the styling of C:\Projects\service-page\node_modules\react-dom\cjs\react-dom.development.js as it exceeds the max of 500KB.
wait - compiling /_error (client and server)...
event - compiled client and server successfully in 47.8s (176 modules)
error - SyntaxError: Unexpected token 'export'
Can you please advice what wrong I am doing here.

There's a workaround. You can use next-css. It seems to be a duplicate of https://stackoverflow.com/a/55255918/19135131
Does it help you?

Related

How to add #svgr/webpack to craco.config?

Similar to this question - I want to be able to load svgs in my reactjs app using the following syntax below. I'm using craco so it doesn't work by default.
import {ReactComponent as MyLogo} from "./svg/MyLogo.svg";
// ...
return (
<MyLogo />
);
My craco.config.js is...
const CracoAlias = require("craco-alias");
module.exports = {
plugins: [
{
plugin: CracoAlias,
options: {
source: "tsconfig",
// baseUrl SHOULD be specified
// plugin does not take it from tsconfig
baseUrl: "./src",
/* tsConfigPath should point to the file where "baseUrl" and "paths"
are specified*/
tsConfigPath: "./tsconfig.paths.json"
}
},
],
webpack: {
configure: (config, { env, paths }) => {
config.module.rules.push({
test: /\.svg$/,
use: ["#svgr/webpack"]
});
return config;
}
}
};
Not sure if this is the right way to hook up #svgr/webpack to my craco config.
Currently, it doesn't work and errors with this...
import {ReactComponent as MyLogo} from "./MyLogo.svg";
// Error Module '"*.svg"' has no exported member 'ReactComponent'.
// Did you mean to use 'import ReactComponent from "*.svg"' instead?
How can I make this work properly using craco?

React + Rollup - 'r is not defined'

Final edit: Thanks everyone for your help, however ultimately it was easier for me to transition to Webpack and Storybook. I'm leaving my original question untouched just in case it helps anyone in the future. Also, if anyone stumbles upon any issues configuring these (like I did), the link to the GitHub repo is below.
I'm creating a small lib using React and Rollup and trying to test locally with a CRA-powered project, however I'm facing this issue when importing a component from my library. I don't know if the problem is in my configuration or if this is a bug.
Uncaught ReferenceError: r is not defined
at Object.../dist/bundle.js (index.jsx:44)
Imported "Message" component where the error is happening
import React, { useEffect, useState } from 'react';
import { string, number, arrayOf } from 'prop-types';
import Container from './Container';
function Message({
text,
type,
timeout,
classes,
}) {
const [show, setShow] = useState(false);
useEffect(() => {
if (text && type) {
setShow(true);
setTimeout(() => setShow(false), timeout);
}
}, [text, type]);
const date = new Date();
return (
<Container
id={`message-${date}`}
key={`message-${date}`}
className={`${type}${classes?.map((className) => ` ${className}`)}`}
>
{
show
? (
<p>{text}</p>
) : ''
}
</Container>
);
}
// The source map points to this line when the error happens, but it still happens if I remove it and don't use prop-types, instead pointing to the closing bracket of the 'Message' function
Message.defaultProps = {
timeout: 3000,
classes: [],
};
Message.propTypes = {
text: string.isRequired,
type: string.isRequired,
timeout: number,
classes: arrayOf(string),
};
export default Message;
Test component where it's being used:
import React from 'react';
import { Message } from 'pure-ui';
import { getRandomArrayElement } from 'formatadores';
const types = [
'warning',
'error',
'success',
];
const texts = [
'This is a test',
'I will randomly display a message every so often, so stay sharp',
'Yet another test message',
];
const timeouts = [
5000,
3000,
1000,
];
function App() {
return (
<div>
<h1>Running...</h1>
<Message
type={getRandomArrayElement(types)}
text={getRandomArrayElement(texts)}
timeout={getRandomArrayElement(timeouts)}
/>
</div>
);
}
export default App;
rollup config file:
import babel from '#rollup/plugin-babel';
import resolve from '#rollup/plugin-node-resolve';
import commonjs from '#rollup/plugin-commonjs';
import external from 'rollup-plugin-peer-deps-external';
import React from 'react';
import propTypes from 'prop-types';
const extensions = ['.js', '.jsx', '.ts', '.tsx'];
export default [
{
input: 'src/index.js',
watch: true,
output: {
file: 'dist/bundle.js',
format: 'iife',
sourcemap: true,
globals: {
react: 'React',
'react-dom': 'ReactDOM',
'prop-types': 'PropTypes',
},
},
plugins: [
external(),
babel({
exclude: 'node_modules/**',
presets: [
'#babel/preset-env',
['#babel/preset-react', { runtime: 'automatic' }],
],
}),
resolve({ extensions }),
commonjs({
namedExports: {
react: Object.keys(React),
'react/jsx-runtime': ['jsx', 'jsxs', 'Fragment'],
'react/jsx-dev-runtime': ['jsx', 'jsxs', 'jsxDEV'],
'prop-types': Object.keys(propTypes),
},
}),
],
external: [
'react',
'react-dom',
'prop-types',
],
},
];
I tried changing the namedExports (and also removing them), linking React from the lib to use the same version from the CRA project (in the lib both React and React DOM are listed as peer dependencies), but I always end with the same result. Is there something wrong with my config? This is the first time I use Rollup for creating a React component lib, so maybe there's something I missed
If the above info is insufficient, here's the GitHub repo
Thanks in advance
Edit: I just saw that I forgot to import React in my test project, however after doing so the results were the same, editing my original question just to fix that.
Update 1: I changed several configurations (changed deprecated rollup-plugins to their currently maintained versions, added globals to the output part of rollup.config.js, added namedExports to commonjs plugin configuration, added an external section specifying react, react-dom and prop-types), but now what I'm getting is a React is not defined error, updating the question with the new config

No syntax highlighting with React Monaco Editor

Just installed React Monaco Editor and seems to be functioning properly except there is no syntax highlighting. I'm trying to use "python" as the language but the font stays the same gray default colour:
Any ideas on how to correct the issue?
Here is my Code.js where I'm running the Monaco Editor:
import React from "react";
import MonacoEditor from "react-monaco-editor";
class Code extends React.Component {
constructor(props) {
super(props);
this.state = {
code: 'print("Hello, World!")'
};
}
editorDidMount(editor, monaco) {
console.log("editorDidMount", editor);
editor.focus();
}
onChange(newValue, e) {
console.log("onChange", newValue, e);
}
render() {
const code = this.state.code;
const options = {
selectOnLineNumbers: true,
fontSize: 18,
colorDecorators: true
};
return (
<MonacoEditor
width="800"
height="600"
language="python"
theme="vs-dark"
value={code}
options={options}
onChange={this.onChange}
editorDidMount={this.editorDidMount}
/>
);
}
}
export default Code;
Also I added this code to the top of webpack.config.js:
const path = require('path');
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = {
plugins: [
new MonacoWebpackPlugin({
// available options are documented at https://github.com/Microsoft/monaco-editor-webpack-plugin#options
languages: ['python']
})
]
};
const APP_DIR = path.resolve(__dirname, './src');
const MONACO_DIR = path.resolve(__dirname, './node_modules/monaco-editor');
module.exports = {
test: /\.css$/,
include: APP_DIR,
use: [{
loader: 'style-loader',
}, {
loader: 'css-loader',
options: {
modules: true,
namedExport: true,
},
}],
}, {
test: /\.css$/,
include: MONACO_DIR,
use: ['style-loader', 'css-loader'],
}
If you are using the Monaco editor with create-react-app you will need a different approach, if you don't want to eject the app (to allow manually editing the webpack config file). This paragraph describes it pretty well:
The easiest way to use the react-monaco-editor with create-react-app is to use the react-app-rewired project. For setting it up, the following steps are required:
Install react-app-rewired: npm install -D react-app-rewired
Replace react-scripts by react-app-rewired in the scripts section of your packages.json
Create a config-overrides.js in the root directory of your project with the following content:
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
module.exports = function override(config, env) {
config.plugins.push(new MonacoWebpackPlugin({
languages: ['json']
}));
return config;
}
For more information checkout the documentation of react-app-rewired
here.
I did not have to specify anything else to make it work. No need to specify loaders for webpack manually.
For me both of the above answers are not working - not sure if it's related to Codesandbox or I did a mistake.
But using #monaco-editor/react is working with-out any changes to the CRA setup.
The only difference in the usage is that the default export is not a controlled component - so onchange is not working.
To have a controlled component, just use import {ControlledEditor as MonacoEditor} from "#monaco-editor/react". The onchange handler needs to be slightly modified, first the event & then the newText - just a small difference in the implementation.
The usage looks like following:
import React, { useState } from "react";
import { ControlledEditor as MonacoEditor } from "#monaco-editor/react";
export const Editor = () => {
const [code, setCode] = useState(`const greeting = () => {
alert("Hello world");
}`);
const options = {
minimap: {
enabled: false
}
};
const changeHandler = (evt, newText) => {
setCode(newText);
};
const editorDidMount = (editor, monaco) => {
console.log("editorDidMount", editor);
};
return (
<MonacoEditor
width="100%"
height="100%"
language="javascript"
theme="vs-dark"
value={code}
options={options}
onChange={changeHandler}
editorDidMount={editorDidMount}
/>
);
};
The options can be used to modify the Monaco editor. In my case I don't want to display the minimap. All available options can be found in the editor api docs
You can find the working demo in this Codesandbox.
The only thing that I found that is not working is undo/redo as described in the following issue. No change event triggered but I'll check this later - for now I'm happy with it.
Did you fail to configure CSS for Monaco Editor in Webpack? Perhaps that's issue since everything else looks good.
const path = require('path');
const MONACO_DIR = path.resolve(__dirname, './node_modules/monaco-editor');
{
test: /\.css$/,
include: MONACO_DIR,
use: ['style-loader', 'css-loader'],
}
Solution
The Problem was nothing with the configuration but the place where it was configured.
To customize webpack in your React CRA boilerplate, you must eject the app or use customize-cra if you don't want to eject, and do the configuration. OP here configured webpack inside node-modules/, That's not the right to configure your webpack, like at all. Use react-app-rewired with customize-cra.

React Storybook SVG Failed to execute 'createElement' on 'Document'

I'm trying to add Storybook to an existing React app but getting errors with imported svg files. The svg is imported and used like:
import Border from './images/border.inline.svg'
...
<Border className="card__border" />
This works when the app is run and built, but I get an error in Storybook. How come?
Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/border.inline.258eb86a.svg') is not a valid name.
Error: Failed to execute 'createElement' on 'Document': The tag name provided ('static/media/border.inline.258eb86a.svg') is not a valid name.
The default webpack.config.js has:
...
{
test: /\.inline.svg$/,
loader: 'svg-react-loader'
},
...
Also, the existing code uses webpack 3, and I'm using Storybook V4.
This is happening because Storybook's default webpack config has its own svg config:
{
test: /\.(svg|ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani)(\?.*)?$/,
loader: 'file-loader',
query: { name: 'static/media/[name].[hash:8].[ext]' }
},
I'm pretty sure this is the cause, because you can see the path outlined in error message: query: { name: 'static/media/[name].[hash:8].[ext]' } -> static/media/border.inline.258eb86a.svg
The solution can be to find the existing loader & change / or add an exclude rule to it. Here's an example of a custom .storybook/webpack.config.js:
// storybook 4
module.exports = (_, _, config) => {
// storybook 5
module.exports = ({ config }) => {
const rules = config.module.rules;
// modify storybook's file-loader rule to avoid conflicts with your inline svg
const fileLoaderRule = rules.find(rule => rule.test.test('.svg'));
fileLoaderRule.exclude = /\.inline.svg$/;
rules.push({
test: /\.inline.svg$/,
...
}],
});
return config;
};
It appears that Storybook V6 they have changed the default Webpack config. I found that the above answers didn't work for me.
They no longer have an SVG rule, therefore testing for SVG will either error or return back undefined.
There is a oneOf rule on the module.rules which contains a loader without a test as the last rule:
{
loader: '/Users/alexwiley/Work/OneUp/resources/client/node_modules/react-scripts/node_modules/file-loader/dist/cjs.js',
exclude: [Array],
options: [Object]
}
This is the culprit, you need to make sure that the file load is excluding all inline SVG file otherwise it will error.
Add the following to your .storybook/main.js file:
webpackFinal: async(config, { configType }) => {
config.module.rules.forEach((rule) => {
if (rule.oneOf) {
// Iterate over the oneOf array and look for the file loader
rule.oneOf.forEach((oneOfRule) => {
if (oneOfRule.loader && oneOfRule.loader.test('file-loader')) {
// Exclude the inline SVGs from the file loader
oneOfRule.exclude.push(/\.inline\.svg$/);
}
});
// Push your SVG loader onto the end of the oneOf array
rule.oneOf.push({
test: /\.inline\.svg$/,
exclude: /node_modules/,
loader: 'svg-react-loader', // use whatever SVG loader you need
});
}
});
return config;
}
In Storybook 6, You have to import it like this:
import { ReactComponent as Border } from './images/border.inline.svg'
Try that if it also works for your version since this question is from a year ago.
This is another way that fixed the issue for me
import Border from './images/border.inline.svg'
And then in your code
<img src={Border} alt="Border" className="w-25"/>
I got it working with
...
module.exports = {
module: {
rules: [
{
test: /\.inline.svg$/,
loader: 'svg-react-loader'
}
]
}
}
For me it was happening as I was using wrong tag name:
import React from 'react';
import RMDBLogo from '../../images/react-movie-logo.svg';
import TMDBLogo from '../../images/tmdb_logo.svg';
import { Wrapper, Content,LogoImg,TMDBLogoImg } from './Header.styles';
const Header = () => (
<Wrapper>
<Content>
<LogoImg src={RMDBLogo} alt='RMDBLogo' />
<TMDBLogo src={TMDBLogo} alt='TMDBLogo'/>
</Content>
</Wrapper>
);
export default Header;
I had imported TMDBLogoImg component while I'm using TMDBLogo tag inside Content tag.

babel jsx SyntaxError: Unexpected token

I'm a learner of react and run into a bug that I don't know how to solve.
I first write the code on codepen, and it runs without problem. Here is the link to my codepen. After exporting it to the local machine, I setup the webpack to handle the compilation. And I receive the error of unexpected token.
After reading all the answers with this title, I still can't solve my bug.
I've updated my webpack cofig file according to the answers, re-installed the dependencies, used a couple of other react boilerplates(1, I currently use this one, but I've also tried some other react starter templates). After I remove the code that the console indicates, I've got another bug pointing to other place in the code.
Thanks in advance.
And here are my codes.
part of the webpack.config.js:
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['react', 'es2015']
}
}
.babelrc:
{
"presets": ["es2015", "react"],
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}
CommentList.js:
import React, { Component, PropTypes } from 'react'
import Comment from './Comment'
class CommentList extends Component {
render() {
const CommentNodes = this.props.data.map((comment)=>{
return (
<Comment author={comment.author} key={comment.id}>{comment.txt}<Comment/>
)
})
return (
<div className="commentList">
<h2>Comments:</h2>
{CommentNodes}
</div>
)
}
}
CommentList.propTypes = {
data: PropTypes.array.isRequired
}
export default CommentList
the error:
/Users/liulian/Documents/React-flux/react-boilerplate/src/components/commentBox/CommentList.js
22:9 error Parsing error: Unexpected token
Module build failed: SyntaxError: /Users/liulian/Documents/React-flux/react-boilerplate/src/components/commentBox/CommentList.js: Unexpected token (22:8)
Points to lines of code below, beginning from line 21 to line 25:
CommentList.propTypes = {
data: PropTypes.array.isRequired
}
export default CommentList

Resources