lerna monorepo package structure - reactjs

I am building a monorepo for a suite of React apps, and common library code. One of the packages would be a component library.
packages
app1
app2
common-ui
alert
button
I'm pretty new to the whole React/node ecosystem.
I've looked at a lot of actual UI library examples - react-bootstrap, material-design-components-react, etc.
It seems I would want to have each component in the common-ui lib to be distributed as single files, so that they can be cherry-picked when imported into a consuming app.
react-bootsrap does this by using babel to build the "lib". They build into a browser distributable, a commonjs lib, and an ES lib.
material-design-components-react does this by having their component lib itself by a lerna monorepo, with each component having its own package.json, and I believe they use webpack to build each component individually.
So my first question is,
Is a structure like material-design-components-react in my common-ui folder - kind of a monorepo within a monorepo possible?
Or would I have to restructure:
packages
app1
app2
alert
button
My second question is,
Which design is recommended by the community for a component library within a major monorepo? This must be a common structure developers have to solve when they have many client apps with common libraries. A package per common-ui component seems like a lot of overhead, but of course they have scripts to help out.

Is a structure like material-design-components-react in my common-ui
folder - kind of a monorepo within a monorepo possible?
Yes it's possible. But keep in mind, you and those libraries have very different requirements. You can think of your monorepo as small projects developed in same company., which are depending on similar 3rd party libraries and they follow same linting, testing etc.
Which design is recommended by the community for a component library
within a major monorepo? This must be a common structure developers
have to solve when they have many client apps with common libraries. A
package per common-ui component seems like a lot of overhead, but of
course they have scripts to help out.
First structure with 3 packages is most common way to start your repository/project.
In your case, I wouldn't recommend to divide your ux-library into single files. Your apps will likely use most of your ux-library and probably you won't have as much components as material or bootstrap has. Moreover, if you'd ever reach that point in your library, you can separate them later. For reference you can also check how lodash is publishing each of their functions. It's not different than your case (assuming you won't publish any fonts/images etc.).

Related

Should the complex components of react be moved to library?

I'm new to react development. I'm currently using Typescript for react with webpack and npm.
i'm working on a large scale project where components are complex. As of now they are kept in certain hierachy in project folder.
i recently learn about making components library. I'm thinking of taking complex components out of project and put them in a separate component library. However, other team members say it would cauae headache to maintain library separately. since there is less to no chance of using this in any other project (thats the current situation) they should not take the components out and maintain separately.
i want to know if that is the only reason the react developers create component and creating component to test it better and simplifing thw project complexity are not the valid reasons?

Common React Components across multiple apps

We have 3 react apps. Some of the components being used in these apps are common for the 3 apps. We want to have a separate common git repo, where we can put the code for the common components and use those components in the 3 apps. Currently, we do have a repo for common components which is linked from the 3 apps like this in package.json:
package-name username/repo#commit-id
This arrangement poses some difficulties:
For some reason, hooks don't work in the common repo even if we upgrade the react version.
While developing locally, we change package.json to package-name ../path. Everytime we make a change locally in the common repo, the common repo has to be built again manually.
Overall, the process is not good. Many times it throws strange errors which are hard to solve.
Can you suggest an alternative way to accomplish the same?
For some reason, hooks don't work in the common repo even if we upgrade the react version.
Treat the component package as its own project. It should have its own package.json that declares its dependencies.
It sounds like you are trying to develop the component package at the same time you develop the other projects that use them. Instead, you should develop the component package in its own environment. If you find problems or think of new features to add to the component package while you work on a project that uses it, create new issues for the component package project and work on them there.
The projects that use this component package should declare a specific version (either by a tag or a commit) which they use. Upgrading to a new version of the component package should follow the same process as upgrading versions of a 3rd party package, such as React itself.

How to correctly handle PeerDependencies when working with a Components Libraries?

First of all, thank you for reading and trying to understand this question.
In my team we have built a library for common Components with React for about 2+ years. This library is built with Babel creating two different transpilations. One in CommonJS for our Test Runner to run tests (because Jest cannot use ESM) and another one in ESM for Create React App (Webpack inside) to make Tree Shaking possible. We use Create React App to build and develop our Apps.
This is working for us perfectly. But we have encounter a problem when managing Final Form Peer Dependencies (or any other library). This is our scenario:
Common Components Library
PeerDependencies
Final Form
DevDependencies
Final Form
App1
Dependencies
Common Components Library
Final Form
App2
Dependencies
Common Components Library
Final Form
App3 (It dont use FinalForm but it uses other Common Components)
Dependencies
Common Components Library
I'll explain this:
In our Common Components Library, which I spoke earlier, we have React Components that works with Final Form, like for example a Vitaminated Autocomplete Text Input Component that we share among many Apps. This Apps also use Final Form to create Components that implement forms locally for that App.
So App1 is right. Everything works fine. But for one thing, now if we want to upgrade Final Form version for this App because, lets say, we need a bug fix of Final Form. We are been forced to upgrade also our Common Components Library and the other App's Final Form version. We need to do this if we want to avoid execution errors within the Final Form React Context. If you are familiar with Final Form or React Context in general you probably have encountered this problem. You can't use different versions of a library that uses React Context. i.e: if we have final-form#1.2.3 in our Common Components Library and final-form#1.2.4 in our App1 it would genereate an execution error. So as I said, we are forced to upgrade not only on App1 and Common Component Library also on the other Apps that uses a Common Component on the Library that uses Final Form. The statement would be: 'Now, if we upgrade somewhere we have to upgrade everywhere'. And we don't want to do that. Probably we aren't handleling dependencies correctly.
So this drove us to move Final Form dependencies (we also use react-final-form, final-form-arrays, etc...) to PeerDependencies. Our problem was solved. But now, another one appeared when we saw that in Apps like App3 we were having an error when we build our App3 with Create React App. This is our output when using npm run build:
module not found `react-final-form' in file 'node_modules/CommonComponentsLibrary/VitaminatedAutoCompleteTextInput.js'
This means that, even with our App not using this VitaminatedAutoCompleteTextInput when we build its checking for every import in the node_modules so this is making us unable to build our App3. When we add the 'missing' depednencies to our App this builds with no problem and then when analyzing our bundle with source-map-explorer we see that final form depdenencies are not included in the bundle.
Is this necessary? I felt like we are missing something here. One solution for us has been including final form depdnencies on the Common Components Library as 'normal' dependencies but we were still having the first problem I mentioned before.
Maybe this problem is not only related with Create React App or Final Form. This is probably a more global isse within ESModules Libraries with Npm dependencies. Probably you will need me to enchance the explanation or have questions. I'll be glad to improve this question where needed. I have also searched on Google and here to find a similar question but I only found this. I dont know exactlcy if it's the same question but It have no answer yet.
Many thanks for trying to help or understand this issue,

Integrating React / Preact based widget library into a legacy web app

A client has request me to build a set of reusable components / widget to be integrated on legacy web development (JQuery, ES5 based).
My idea is to create:
A library that will make use of React / Preact to build the widgets.
Use ES6/TS + webpack + babel, to end up transpiling to ES5 and packing it into a library.
My main concern comes with the third party libraries dependencies(e.g. react, react-dom or preact…), I’m thinking about taking one of this two approaches:
A. Treat third party libraries as just external dependencies, the legacy application that needs to consume my widget library have to reference that library.
Pros: no extra weight added to my bundle, this library could be used in legacy apps and modern apps.
Cons: possible versioning hell in the future, e.g. we release the library for React 16, and in the future, they mix other widgets from another library that depend on React 18 (maybe a possible workaround is to fix versions and perform an all or nothing migration from time to time).
B. Embed preact into the library bundle:
Pros: only adding 3 to 4 Kb to the library bundle, the bundle is self contained.
Cons: probably we could not use these components on modern development (e.g. compose it with other components from other react based libraries).
What could be the best approach? Is there another option available? Does approach B make sense? (haven’t tried that one before).
I would lean to the B answer.
if you need to combine them with other libraries, you still have the sources in ES6+ which allows you to import them easily inside a new project.
I actually only work with the B approach because it removes the dependency nightmare. You know that you ship code with the compatible react version, and you have total control of the final ES5 code with babel.
If you worry that much over 10kb, there's plenty of ways to reduce size (enabling compression, making sure you use production bundle, etc).

managing common libraries in AngularJs

I am developing an application with a few modules. Each module is individually deploy-able on the server. I am using Angular for my UI.
Because I have 4 modules, I obviously have 4 different Angular projects, setup & files.
Though there are certain differences like routing, controllers, views, the external frameworks, libraries used can be very similar and I do not want to replicate all of them.
Hence I wish to have a common project/folder/directory and use these in different modules. this way I can avoid redundancy (if it can be called that). Can someone please help me understand if my thought process is correct? If so how can I achieve this?
Use a third party package manager like npm or bower. You can then add the libraries during build time with browserify or custom gulp/grunt code.
You can then bundle all you libraries into a single file and include it in you application.

Resources