Control/Customize Component name minification in Production React - reactjs

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()
],

Related

Can I build an chrome extension from an existing React application?

So I have an existing Create React Application and I want to be able to build a chrome extension to work in conjunction with it. Is there a away I can use webpack or something so that my extension kind "lives in" the React application? I want to do this because the existing application is quite large and I don't want to have to make changes (UI, api, or otherwise) twice. In my head I'm picturing it something like this:
- MyApplication/
- src/
- index.html
- App.tsx
- components/
- <bunch of other useful stuff>
- extension/
- index.html
- Extension.tsx (equivalent of App.tsx in react app)
Basically I'd be able to import whatever I need into the extension and run some command like build extension and it would bundle just the files and dependencies imported and necessary for the extension and output that to some directory I can upload to the Chrome Web Store.
I also briefly considered splitting the application into into something like MyApplication-core, MyApplication-web, and MyApplication-extension or something and just installing core in both web and extension but not sure if that's the best strategy or not. The first strategy I outlined seems simpler to maintain but I could be wrong.
Also, if there is another strategy I haven't thought of please let me know! Happy to add clarification if necessary as well! TIA!
Just build it and add manifest with required configurations. After this you will have posibility to load it as an extension.

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

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.

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.

React Loadable SSR isn't always giving client complete list of bundles, leading to page flash

I've been struggling for the last few days to eliminate page flash. My project started with create-react-app, then I used help to set up SSR and various other options. When I started running into problems, I stripped my code down and ejected. Here is my code. You can build with npm run build and start the SSR with npm run serve. Visit http://localhost:3000/ to see the result.
There are two routes in my app: Home and About.
Going to / (Home) works as desired: react-loadable identifies the home bundle, injects a <script> tag for it, and sends the page out the door. The client loads all the bundles and react takes over with no flash.
Going to /about results in a page flash (make sure the page is loaded from the server to see this). I added an import for moment-timezone into the about component, and webpack smartly moves it into its own bundle, separate from the about bundle. The problem is that react-loadable only sees that it needs the about bundle, not the extra bundle containing moment-timezone. Thus, on the client side, when react takes over it sees that its missing a module, blanks the page, loads the bundle containing the missing module, then re-renders (at least,
I think that's how it works).
What am I missing? I am using the babel and webpack plugins as described in the React-Loadable Readme. It seems like React-Loadable is only smart enough to go one level deep and not see what the imported module's dependencies are, but surely that's not the case, is it?
This happens because react-loadable don't have a nice and deep implementation for server side rendering.
But the good news is, there's an add-on for that, it is called react-loadable-ssr-addon.
In the plugin repository it says:
React Loadable SSR Add-on is a server side render add-on for React Loadable that helps you to load dynamically all files dependencies, e.g. splitted chunks, css, etc.
Oh yeah, and we also provide support for SRI (Subresource Integrity).
So basically this plugin handle everything regarding the assets situation for server side rendering in react, reproducing the same behaviour as the tradicional approach (client side render).
With that, your assets are managed and loaded automatically to your output, avoiding the error you reported.

Resources