Several instances of 'styled-components' initialized in CRA micro-frontend application - reactjs

I'm running a micro frontend application with multiple React versions, each micro frontend repo is using lazy loading for dynamically loading its React version and it works as expected (Yay!)
The micro frontend app is structured as follows:
That being said, I am experiencing issues with the styled-components multi-versioning, and receiving the following console warning in dev mode (not in production):
For more technical details check out the example repo with the implementation.
Since the application is using CRA to simplify the configurations of webpack/babel I was wondering if there is a good way to improve the initial configuration to resolve this console warning.
I checked the docs link shared on the warning, and while I understand micro frontend wouldn't be the best way to maintain your project, we'd still like to provide this option to our users as they might need to gradually migrate their project versions, so I'm still interested in getting this console warning resolved.
Any tips or suggested solutions would be appreciated.
printed warning:
react_devtools_backend.js:2430 It looks like there are several instances of 'styled-components' initialized in this application. This may cause dynamic styles to not render properly, errors during the rehydration process, a missing theme prop, and makes your application bigger without good reason.
See https://s-c.sh/2BAXzed for more info.

I was facing the same issue and I solved it by moving all my styled components inside remote apps and exposed them from there.

I had the same issue with my micro-service application. For each micro-service I had package.json file and one global package.json for all micro-service. So, in the global package.json I added resolution, it allowed me to have only one version of styled component for my app
"resolutions": { "styled-components": "4.2.1" },
Also, I used to lerna. It can help you with your micro-service's dependencies.
I hope my answer can help you resolve your problem.

Related

Control/Customize Component name minification in Production React

Background
I often use "React Developer Tools" to understand the component structure of various website that I like and take inspiration from. Though, lot of websites have random names for the components, few websites have distinguishable names which can be helpful for aspiring React Developers or hobbyists. One such website is https://www.joshwcomeau.com. Below is a screenshot from one of the pages in his website. The name of few of the components explains itself what it is going to render. And since this is his blog, where he talks about various tips and tricks for React Development, it becomes helpful to have a look at this.
Question
Now when I develop a website using create-react-app(CRA), all my component names are minified to a couple of random letters by Webpack. How can I control this behavior?
Note: My main question is - How to control this behavior in any React application (not just CRA). I know that Josh uses Next.js for his blog, so does any framework like Gatsby, Next etc... provide control over this?.
Note:
I'm aware that the component names are visible in development mode, but I would like it to be visible in production too (for the reason explained above in "Background").
I'm aware that webpack can generate "sourcemap" but doing that would expose my entire code structure. So I prefer not to use sourcemaps
Screenshot of Josh's Website
Screenshot of My Website
You can achieve this with a third party library:
From webpack-react-component-name documentation:
Normally React component names are minified during compilation. This plugin makes these component names available in production bundles by hooking into Webpack's compilation process, traversing the AST looking for React component definitions and updating the emitted source code to populate the displayName property. This is the property that, when populated, is used by the React Dev Tools extension to determine the name of a component.
So you can install this webpack plugin with:
npm install webpack-react-component-name -save-dev
once it is installed, add the plugin to the plugins list in webpack configs:
plugins: [
new WebpackReactComponentNamePlugin()
],

REACTJS.NET SSR - Object doesn't support property or method 'forwardRef'

I am trying to render my REACT components via SSR with REACTJS.NET in ASP.NET project.
In the JS file for SSR, I'm importing SimpleBar component from simplebar-react package.
This is causing the error TypeError: Object doesn't support property or method 'forwardRef'.
I currently have 2 JS files, one for server and one for client. In the JS for server I am removing the adding of event listeners and similar. However, I can't get away from importing at least the npm package in both JS files.
Any idea on how I can avoid such error?
I am using Webpack + REACTJS.NET version 3.2.0.
So, after trying a lot of things, this is the best solution I came across.
Before I begin, I am aware that conditional imports is being introduced in ECMA but it isn't working for me, or at least, they way I have the project setup.
Basically, my solution is resolved by mixing ES6 with CommonJS and with help of Webpack and babel.
In Webpack I am creating a plugin:
And in code, when I want to import the Simplebar react component, I do the following in the constructor:
And then, whenever I want to use my imported component, I do the following:
This was the best way I found in order to render with SSR. I think it's okay since the content between server and client side are the same.
Does anyone know a better solution? Or do you have concerns?

What is the correct way to include React in both an application and a private library? (React Invalid Hook Call warning from duplicate React)

I have a sort of a "monorepo", one big project consisting of a few smaller projects that use React.
I'm trying to break these up into three separate repositories, lets call them Core, Application1, and Application2
The Core is a dependency of both applications, and the Core depends on React, because it defines some React component classes. The applications both also use React.
When I tried to build this all together (using Parcel bundler), I am getting a final bundle which at runtime gives the Invalid Hook Call warning in one (but not both) of the applications.
On that page (or in the error message), it says that the error could be caused by one o these:
You might have mismatching versions of React and React DOM.
You might be breaking the Rules of Hooks.
You might have more than one copy of React in the same app.
I have checked that #1 is not true, and I'm not even using hooks in any way that I am aware of, so the problem is seems to be multiple versions of React.
I gathered from reading about this that it was a mistake for my Core library to declare React as a dependency, and that it should instead declare it in peerDependencies. That made the Application stop giving the error, but it also made my Core library start having a bunch of Typescript errors and failing to be able to run the unit tests (which rely on React, using Jest/Enzyme to render and validate DOM).
Since specifying React in peerDependencies caused it not to be installed in the node_modules of Core, I decided that I should probably include React in both the peerDependencies and the devDependencies of Core. That fixes the Core library again but breaks the Application.
I'm not really sure of the following:
Why one of my applications fail due to duplicate React copies and the other doesn't, since they seem pretty symmetrical to each other.
Why, even though I only specify React in peerDependencies and devDepenencies in Core I still would get a duplicate copy of React in the dependent application
Whether the method used to bring Core in to the application has any bearing on this. (one method I'm trying is package.json I specify core as a "file:../" style of URL. Another alternative is to use "yarn link", or possibly to do both of these, and I'm not sure whether this has any effect on what ends up in node_modules underneath the application folder or on what gets bundled)
What is the right way to include React in both an Application and a library, in such a way that both of those projects have React available but there does not end up being duplicates in the Application causing this hook error (or, just taking up extra space).
Answering my own question.
I found the following issue helpful: https://github.com/facebook/react/issues/14257
Various different suggestions were made in the comments of ways to solve this problem, either by npm link or yarn linking the react library from the library to the application, or vice versa. Those all seemed promising, since the idea is to make sure that all of the different references to React are actually pointing to the same place. Unfortunately none of those worked for me. (e.g. the answers by JerryGreen and Kas in that issue)
Another user, dcecile, suggested using webpack's alias feature, but I'm not using webpack.
resolve: {
alias: { react: require.resolve("react") }
},
Parcel has a similar alias feature but can't be used in quite the same way because it's used in the package.json file so things like require.resolve can't be called like they are in webpack's js config file.
I ended up finding a way to use Parcel's alias feature to do what I wanted, based on another example from https://github.com/jaredpalmer/tsdx/issues/64 from user jaredpalmer. In my situation, I'm adding this to the application's package.json, and it appears to get rid of the duplication problem and the "Invalid Hook Call" error:
"alias": {
"react": "../my-core-library/node_modules/react",
},

Issue on Product version of Styled-Components when render with Rendertron

have very simple sample app which build Create React App + Styled-Components to prove this issue. But I have real big application which I am facing this issue which I am going to explain it below.
I would like to pre-render this app with Rendertron for SEO/GoogleBots and etc. But the problem is when I build PRODUCTION version of React App which use Styled-Components . all the style will be missing on static version which Rendertron produced, but from other side if I try the same workflow with dev-server of app , everything looks fine .
So far I know there is different on PROD version and DEV version of my application when I render it with Rendertron . But I am not sure what cause this issue and how I can fix this issue .
I am looking for solution or idea which can help me to solve this issue .
Here is my sample code which I peppered for test .
https://github.com/AJ-7885/test-styled-component-with-rendertron
Here is screen shot from different version of Rendered version by Rendertron base on PROD or DEV version of the same application .
enter image description here
After a lot of searching around, I finally found out the reason. The Styled Components library uses something called the "Speedy mode" to inject styles on production. This makes the styles bypass the DOM` and be injected directly inside the CSSOM, thus, appearing in the inspector, but totally invisible on the DOM.
Fortunately, Styled Components 4.1.0 came with a fix for this issue! Now you can set a global variable called SC_DISABLE_SPEEDY to true in order to disable the Speedy mode and get the styles to appear on Production as well.
Reference: https://www.styled-components.com/releases#v4.1.0
But the only part I am not sure , how to set disable this Speedy Mode in Create-React-App without Ejecting , Dose any body has any idea ?
You need to render your styles on the server side and inject those styles in your pre-rendered react app. Styled-components explains how to do that here: https://www.styled-components.com/docs/advanced#server-side-rendering
Also, I'd recommend using react-snap for pre-rendering since that is recommended by the Create React App docs. react-snap seems to be more of a React-specific solution that may be easier to implement, especially with styled-components.

Getting Parcel Bundler Code Splitting working with React + TypeScript + MobX + ReactRouter

I've been trying to get Parcel Bundler to code split a ReactJS project for a while with no success, this project also used TypeScript, ReactRouter and MobX for its state management.
I've been meaning to put a boilerplate sample together and ask for help here for a while but not got round to it.
After a quick google earlier today, I came across a ready made boilerplate on Github which uses the same setup and also does not code split...
https://github.com/wenpengfei/parcel-typescript-react-boilerplate
Once compiled and ran, it just ends up with one big .js file in the dist folder, the idea behind code splitting is to create several smaller .js files per 'area' of the web application right?
Is this even possible with this combination of libraries/frameworks? If not, is my only option to go down the webpack route instead (if that will work?)?
For client side code splitting just use import + React.lazy. Should work out of the box.
To support server-side code splitting (or client-side code splitting with server-side rendering) - https://github.com/theKashey/react-imported-component is the only choice for today.

Resources