<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vittorio Zamboni</title>
    <description>The latest articles on DEV Community by Vittorio Zamboni (@vittoriozamboni).</description>
    <link>https://dev.to/vittoriozamboni</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F186639%2Facf4b0a0-0f0d-4ac1-bd38-25406262c33d.jpg</url>
      <title>DEV Community: Vittorio Zamboni</title>
      <link>https://dev.to/vittoriozamboni</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vittoriozamboni"/>
    <language>en</language>
    <item>
      <title>borrow-ui: a React component library starter</title>
      <dc:creator>Vittorio Zamboni</dc:creator>
      <pubDate>Wed, 15 Sep 2021 16:34:26 +0000</pubDate>
      <link>https://dev.to/vittoriozamboni/borrow-ui-a-react-component-library-starter-34gg</link>
      <guid>https://dev.to/vittoriozamboni/borrow-ui-a-react-component-library-starter-34gg</guid>
      <description>&lt;p&gt;Hi all! &lt;br&gt;
My name is Vittorio and I am working as full-stack engineer in Nuritas, an AI/Biotech company.&lt;br&gt;
During the last few years, I have worked on several projects (small and big) where I had to learn few things, remembering others and combining different domains. &lt;br&gt;
Almost always these projects required a UI and given my familiarity with React I focused on bootstrapping small POCs/MVPs that had less dependencies as possible (sometimes it was actually a requirement to not rely on any of the big players like Ant, Bootstrap, Material-UI). &lt;br&gt;
While working on these projects I setup a base that allowed me to share previous knowledge and custom additions. With slow pace I finally put it together in a presentable way, releasing it as a repository to &lt;em&gt;copy&lt;/em&gt; or as npm package.&lt;/p&gt;

&lt;p&gt;The name of the project is &lt;code&gt;borrow-ui&lt;/code&gt; and it is available in &lt;a href="https://github.com/borrow-ui/borrow-ui"&gt;GitHub&lt;/a&gt;, with a &lt;a href="https://www.borrow-ui.dev/"&gt;project website&lt;/a&gt; as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Goals of borrow-ui
&lt;/h2&gt;

&lt;p&gt;The goal of this project is to create and maintain a UI component library base for creating POCs/MVPs or new projects (i.e. dashboards), with the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;being extendable in an easy way: adding a new component should be an easy and repeatable operation;&lt;/li&gt;
&lt;li&gt;consistency: the overall experience (both for the user and the developer) should be consistent between components and packages;&lt;/li&gt;
&lt;li&gt;well documented: the components should be clear and simple, and they need to have a good documentation and examples;&lt;/li&gt;
&lt;li&gt;being tested: when your components are supposed to be the core of &lt;em&gt;something&lt;/em&gt; (a dashboard, a website) you just don't have time to test each single scenario manually on every change;&lt;/li&gt;
&lt;li&gt;should have less dependencies as possible, but still be as much complete as possible without reinventing the wheel (for example, the excellent &lt;code&gt;react-select&lt;/code&gt; is used);&lt;/li&gt;
&lt;li&gt;work as self-documentation for configuring the most common scenarios (i.e. bundler, integration with CRA, etc);&lt;/li&gt;
&lt;li&gt;being open source: sharing and contributing is the key of being part of a community, and giving something after all the taking is a great feeling!&lt;/li&gt;
&lt;li&gt;being a playground to learn new things: before starting it, I had no idea of the complexity of creating and maintaining a component library, or how to create an npm package, a monorepo with Storybook, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The component library can be either integrated in an existing project or as a monorepo starter. The project website has a &lt;a href="https://www.borrow-ui.dev/getting-started/getting-started"&gt;getting started&lt;/a&gt; section that can guide in both ways. If you are &lt;em&gt;really brave&lt;/em&gt;, there is also an npm package with all the components of the library ready to be used.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical details (and some comments)
&lt;/h2&gt;

&lt;p&gt;Few keywords first: &lt;code&gt;monorepo&lt;/code&gt;, &lt;code&gt;yarn 3&lt;/code&gt;, &lt;code&gt;rollup&lt;/code&gt;, &lt;code&gt;react-testing-library&lt;/code&gt;, &lt;code&gt;storybook&lt;/code&gt;, &lt;code&gt;mdx&lt;/code&gt;, &lt;code&gt;CRA&lt;/code&gt; and &lt;code&gt;Next.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;borrow-ui started a couple of years ago as a personal project, and given the different requirements the first idea was to organize the library and the actual app/website in different folders. Monorepos are the best solution I could found and initially borrow-ui integrated &lt;code&gt;lerna&lt;/code&gt;. Unfortunately, the &lt;code&gt;lerna&lt;/code&gt; project &lt;a href="https://github.com/lerna/lerna/issues/2703"&gt;seems to be unmaintained&lt;/a&gt; and the issues arose when working with &lt;code&gt;yarn&lt;/code&gt; and some deep interdependencies. For this reason, &lt;code&gt;yarn 3&lt;/code&gt; with workspaces have been chosen: it's more verbose but it does the job.&lt;/p&gt;

&lt;p&gt;The library itself has a small number of components which are tested by the amazing &lt;code&gt;react-testing-library&lt;/code&gt; ("how easy to use is it?!" &amp;lt;- rhetorical question). The coverage of the core components as of today is ~97%. The test suite is run when a pull request is created, using the Travis-CI open source program.&lt;/p&gt;

&lt;p&gt;The library is styled with SCSS, following BEM convention. &lt;br&gt;
Each component also has a Story file written in &lt;code&gt;.mdx&lt;/code&gt;, and shown using the &lt;code&gt;docs&lt;/code&gt; plugin in the &lt;code&gt;documentation&lt;/code&gt; package (a Storybook installation already configured to source the components).&lt;/p&gt;

&lt;p&gt;The component library is bundled with &lt;code&gt;rollup&lt;/code&gt;, which was the lightest choice at the time but still complete for all my use cases. &lt;/p&gt;

&lt;h2&gt;
  
  
  Repository content
&lt;/h2&gt;

&lt;p&gt;The monorepo contains the main package with all the components, called &lt;code&gt;ui&lt;/code&gt;, and other three small packages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;documentation&lt;/code&gt;: a configured Storybook which allows to develop new components very easily, and also produces a good technical reference;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dashboard&lt;/code&gt;: a small example of an application created with create-react-app (CRA), which I use as a base and demo for dashboards before starting new projects. It has two apps, one created to show how to use the components of the library and the other one as a "scalability" example. The code is extensively commented; as a side note, I use this dummy project to show how to organize components and files in a React project;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;website-next&lt;/code&gt;: an example of how to integrate the library in a Next.js app, how to configure it to use &lt;code&gt;mdx&lt;/code&gt; and how to add additional custom components (all this is explained as blog posts in the demo itself).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Challenges (so far)
&lt;/h2&gt;

&lt;p&gt;Creating and maintaining a component library can be really difficult and tiring.&lt;br&gt;
The common scenario (of any library) is when you add something and that slightly changes - or breaks! - something else, but this can be mitigated with a good test suite. Or similarly when you need to change the APIs of a component, and you have to update the dependent applications: reducing this changes is a must for a library.&lt;br&gt;
Choosing other libraries and components to integrate is one nice part of it, while the less-nice part is how to make them look consistent with other components. Two examples are &lt;code&gt;react-select&lt;/code&gt; and &lt;code&gt;react-day-picker&lt;/code&gt; which have excellent APIs but their style does not match with the library one (few times I was tempted to change again and again the UI library instead of adapting the components, but that desperation went away in the end).&lt;br&gt;
The biggest challenge has been maintain the library up-to-date and consistent. If you need to use different components in the same page, they should look (relatively) well together, otherwise the eye is not satisfied and the functionality compromised.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps
&lt;/h2&gt;

&lt;p&gt;Where to go from here? &lt;br&gt;
The two next steps will be creating a dark mode (and possibly treating it as a theme rather then just a binary option) and the conversion to Typescript (or maybe a separated branch?).&lt;br&gt;
Both things are new to me and it will take some time and research before, so any suggestion is welcome (double appreciated if in the issues section of the repository)!&lt;br&gt;
A better roadmap is available on the website, or in the milestones section of the GitHub repository.&lt;/p&gt;

&lt;p&gt;I really hope this project and my trial and errors can be useful to anyone that will have to start a similar journey, even to borrow some configurations or a single component. &lt;br&gt;
It has been hard &amp;amp; funny to work on this project, and I am excited to moving it forward to make it more useful.&lt;/p&gt;

&lt;p&gt;Thank you for reading all this long post!&lt;/p&gt;

</description>
      <category>react</category>
      <category>github</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Mix Netlify DNS and other subdomains</title>
      <dc:creator>Vittorio Zamboni</dc:creator>
      <pubDate>Sun, 14 Jul 2019 17:16:23 +0000</pubDate>
      <link>https://dev.to/vittoriozamboni/mix-netlify-dns-and-other-subdomains-5f11</link>
      <guid>https://dev.to/vittoriozamboni/mix-netlify-dns-and-other-subdomains-5f11</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover image: Wicklow Mountains, Co. Wicklow, Ireland&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The last time I created a blog was few years ago, and WordPress was still the most popular choice to reduce the effort and have a decent piece of functionality.&lt;br&gt;
Recently, after learning some React and following the community choices, I really liked &lt;a href="https://www.gatsbyjs.org/" rel="noopener noreferrer"&gt;Gatsby&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Creating a static blog can reduce the complexity of the architecture: no more database, no more host running PHP, simpler configurations for Nginx.&lt;/p&gt;

&lt;p&gt;A plus is also the possibility to use services like &lt;a href="https://app.netlify.com" rel="noopener noreferrer"&gt;Netlify&lt;/a&gt; to host your blog's build. The main points are: it's free, it builds automatically after a new commit is pushed to your preferred brach and it manages DNS for you.&lt;/p&gt;

&lt;p&gt;Last part is a little bit tricky if you already own a domain and you already have other applications running on different subdomains.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deploy to Netlify
&lt;/h2&gt;

&lt;p&gt;With few easy steps, it is possibly to deploy your repository directly to Netlify. &lt;a href="https://www.netlify.com/blog/2016/02/24/a-step-by-step-guide-gatsby-on-netlify/#connecting-to-netlify" rel="noopener noreferrer"&gt;A blog post&lt;/a&gt; in their website explains really well how to do this. &lt;br&gt;
In summary, you will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add your respository from your Netlify dashboard by clicking on "New site from GIT" (and choose one of Github, GitLab or Bitbucket);&lt;/li&gt;
&lt;li&gt;grant Netlify's app the required permissions;&lt;/li&gt;
&lt;li&gt;proceed with default settings and deploy.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will generate one subdomain for you, like &lt;code&gt;my-netlify-generated-subdomain.netlify.com&lt;/code&gt;: if you navigate to this URL your blog will be there!&lt;/p&gt;
&lt;h2&gt;
  
  
  DNS Provider settings
&lt;/h2&gt;

&lt;p&gt;Following Netlify's guide, I set the domain name (my-domain.io) as Primary Domain and WWW subdomain as domain alias. &lt;br&gt;
This worked perfectly for both of them, but unfortunately I lost access to my other applications reachable by different subdomains (second-app.my-domain.io). &lt;/p&gt;

&lt;p&gt;I then moved my main configuration to my DNS provider built in service (I am using &lt;a href="https://www.gandi.net" rel="noopener noreferrer"&gt;Gandi&lt;/a&gt; as DNS provider and &lt;a href="https://www.linode.com" rel="noopener noreferrer"&gt;Linode&lt;/a&gt; as VM provider).&lt;/p&gt;

&lt;p&gt;I wanted to have my domain (without subdomain), &lt;code&gt;blog&lt;/code&gt; and &lt;code&gt;www&lt;/code&gt; subdomains to point to Netlify, but all other subdomains to point to my Linode instance (with&lt;code&gt;1.2.3.4&lt;/code&gt; as IP address).&lt;/p&gt;

&lt;p&gt;This is the result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@ 10800 IN A 1.2.3.4
@ 10800 IN MX 10 spool.mail.gandi.net.
@ 10800 IN MX 50 fb.mail.gandi.net.
@ 10800 IN TXT "v=spf1 include:_mailcust.gandi.net ?all"
blog 1800 IN CNAME my-domain.io.
second-app 1800 IN CNAME my-domain.io.
www 10800 IN CNAME my-netlify-generated-subdomain.netlify.com.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The first entry says that my primary domain has to be routed to my Linode instance (the other starting with @ are just the default example of a Gandi configuration).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;blog&lt;/code&gt; and &lt;code&gt;second-app&lt;/code&gt; subdomains are routed to my-domain.io;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;www&lt;/code&gt; subdomain is routed to my netlify subdomain.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: you will need DNS entries to propagate before testing, this might take few hours&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure Nginx for redirect
&lt;/h2&gt;

&lt;p&gt;The first line of the configuration alone will not allow us to have our main domain pointing to Netlify's instance: we need to tell it to route to our &lt;code&gt;www&lt;/code&gt; subdomain destination. &lt;/p&gt;

&lt;p&gt;This is the simple Nginx configuration use to redirect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    server_name my-domain.io;
    rewrite ^/(.*)$ http://www.my-domain.io/$1 permanent;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you also want to have your &lt;code&gt;blog&lt;/code&gt; subdomain to point to Netlify, add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;server {
    server_name blog.my-domain.io;
    return 301 https://www.my-domain.io$request_uri;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additional rules will handle your &lt;code&gt;second-app&lt;/code&gt; subdomain.&lt;br&gt;
A standard configuration might be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;upstream second-app {
    server 127.0.0.1:8085;  # stram to a different port
}

server {
    server_name second-app.my-domain.io;
    listen 80;
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_pass http://127.0.0.1:8085;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Netlify DNS configuration
&lt;/h2&gt;

&lt;p&gt;The last step is to configure your domain in Netlify.&lt;br&gt;
By default, guides tells you to set the primary domain as primary domain (obviously!). &lt;/p&gt;

&lt;p&gt;When you do this, a &lt;code&gt;www&lt;/code&gt; subdomain configuration is also added:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo50qmvlq6kgjkrfpaiio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fo50qmvlq6kgjkrfpaiio.png" alt="main-domain-as-primary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this way however you will see some errors in the console due to our configuration, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6n6ihok5t20m5iippyul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F6n6ihok5t20m5iippyul.png" alt="redirect-calls-failure"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To avoid this, we need to swap the configuration in Netlify, by setting our &lt;code&gt;www&lt;/code&gt; domain as primary domain:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flu5hqc8kdr1ynobwphpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flu5hqc8kdr1ynobwphpn.png" alt="www-domain-as-primary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et voila'! All our DNS are setup to work correctly by mixing our host and Netlify.&lt;/p&gt;

</description>
      <category>configuration</category>
      <category>dns</category>
      <category>netlify</category>
      <category>subdomain</category>
    </item>
    <item>
      <title>Include different repositories in a create-react-app project</title>
      <dc:creator>Vittorio Zamboni</dc:creator>
      <pubDate>Tue, 09 Jul 2019 22:33:25 +0000</pubDate>
      <link>https://dev.to/vittoriozamboni/include-different-repositories-in-a-create-react-app-project-207d</link>
      <guid>https://dev.to/vittoriozamboni/include-different-repositories-in-a-create-react-app-project-207d</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover image: Bunbeg Beach, Co. Donegal, Ireland&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When I started writing React applications all the codebase was under a single repository. No code sharing, no context separation.&lt;/p&gt;

&lt;p&gt;As soon as I gain interested in exploring new solutions, I wanted to build a small dashboard at home as a playground to test new libraries, React hooks or integration with other frameworks like Vue.&lt;/p&gt;

&lt;p&gt;Creating the Dashboard backbone was a straightforward operation: a few components for the scaffold, a basic authentication module, a Routes component with few switch cases and an &lt;code&gt;apps&lt;/code&gt; folder to contain the different projects.&lt;/p&gt;

&lt;p&gt;Coming from a Python/Django background, I wanted to organize my code in different repositories as I was doing with all my previous projects. Unfortunately this operation has not been as straightforward as expected.&lt;/p&gt;

&lt;p&gt;In Python there are a couple of tools which I am familiar with and that helped me to manage this requirement: &lt;code&gt;virtualenvwrapper&lt;/code&gt; is one of these.&lt;br&gt;
One of its functionalities (&lt;code&gt;add2virtualenv&lt;/code&gt;) is the ability to link different repositories together under the same environment and still being able to modify them without any re-installation or deployment - another option would be &lt;code&gt;pip install -e&lt;/code&gt; from the repository folder.&lt;/p&gt;

&lt;p&gt;Unfortunately, it's not the same with npm/yarn and &lt;code&gt;create-react-app&lt;/code&gt;; they both allows to &lt;code&gt;link&lt;/code&gt; but each repository must resolve it's own dependencies and have them installed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Project structure
&lt;/h2&gt;

&lt;p&gt;The currenct project structure is based on the standard &lt;code&gt;create-react-app&lt;/code&gt; example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package.json
src/
    apps/
        ...
    libs/
        ...
    scaffold/
        ...
    App.js
    index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My idea was to share the code inside &lt;code&gt;libs&lt;/code&gt; folder to all the applications and to keep each application in it's own repository.&lt;/p&gt;

&lt;p&gt;The first thing I tried was &lt;code&gt;yarn link&lt;/code&gt;, but it didn't worked well. This approach assumes that the code inside the application is already packaged with it's own dependencies resolved. &lt;/p&gt;

&lt;p&gt;Something was missing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid ejecting
&lt;/h2&gt;

&lt;p&gt;The first thing I did was to &lt;code&gt;eject&lt;/code&gt; to explore the configuration opportunities.&lt;br&gt;
This is actually a good way to test out configurations if you can revert (which is pretty easy if you are under a version controlled folder).&lt;/p&gt;

&lt;p&gt;Ejecting (and keeping each config file) however is not my preferred solution because when you go manual for a long period and starts to customize a lot of things you can't easily go back, and you need to maintain the dependencies one by one.&lt;/p&gt;

&lt;p&gt;On the opposite side, &lt;code&gt;create-react-app&lt;/code&gt; does not allow you to modify the configuration files in order to keep the project as generic and standard as possible.&lt;/p&gt;

&lt;p&gt;Few solutions has been suggested on the web: switch to razzle.js, use next.js, rethink the project structure with lerna (the monorepo approach - one owner only) or fork &lt;code&gt;create-react-app&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In order to keep the project simple I didn't want to introduce next.js or razzle.js. I hope to reuse my dashboard code for other projects and using a framework might not be the best solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork
&lt;/h2&gt;

&lt;p&gt;Of all solutions I opted for forking &lt;code&gt;create-react-app&lt;/code&gt; repository, following &lt;a href="https://medium.com/@denis.zhbankov/maintaining-a-fork-of-create-react-app-as-an-alternative-to-ejecting-c555e8eb2b63"&gt;this guide&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;On &lt;code&gt;react-scripts&lt;/code&gt; package, I added the following lines to &lt;code&gt;config/webpack.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;saving the content to a variable instead of returing the configuration directly:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt; remove the return statement and save the content
&lt;span class="gd"&gt;-  return {
&lt;/span&gt;&lt;span class="gi"&gt;+  let config = {
&lt;/span&gt;     mode: isEnvProduction ? 'production' : isEnvDevelopment &amp;amp;&amp;amp;  'development',
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;checking if a file called &lt;code&gt;customWebpack.config.js&lt;/code&gt; exists in the project root folder and, if it has a &lt;code&gt;modify&lt;/code&gt; function, override the config with the function's result:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;     // our own hints via the FileSizeReporter
     performance: false,
   };
&lt;span class="gi"&gt;+  console.log('Checking for custom webpack config');
+  if (fs.existsSync('./customWebpack.config.js')) {
+    console.log('  -- custom config found!');
+    const customWebpackConfig = require(path.resolve(
+      __dirname,
+      '../../../../customWebpack.config'
+    ));
+    if (customWebpackConfig.modify) {
+      config = customWebpackConfig.modify(config, { webpackEnv });
+    }
+  }
+
+  return config;
&lt;/span&gt;&lt;span class="err"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This similar approach is used by &lt;code&gt;razzle&lt;/code&gt; (in a much fancier way).&lt;/p&gt;

&lt;p&gt;On my project then I had to do three things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding a &lt;code&gt;customWebpack.config.js&lt;/code&gt; file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;modify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;webpackEnv&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// List of external repositories that have to be added&lt;/span&gt;
        &lt;span class="c1"&gt;// to the testers to being correctly processed       &lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;externalRepositories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_EXTERNAL_REPOSITORIES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;externalRepositories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REACT_APP_EXTERNAL_REPOSITORIES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Set a list of repositories required for this project&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;projectRepositories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; 
            &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-test-repo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;           
        &lt;span class="p"&gt;];&lt;/span&gt;

        &lt;span class="c1"&gt;// Validate that all repositories have been set before starting&lt;/span&gt;
        &lt;span class="nx"&gt;projectRepositories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;externalRepositories&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;eRepo&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;eRepo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endsWith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`==&amp;gt; Repository &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; must be included in `&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
                &lt;span class="s2"&gt;`.env.local REACT_APP_EXTERNAL_REPOSITORIES variable`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;oneOf&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;oneOf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;include&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;externalRepositories&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;add the repositories to &lt;code&gt;REACT_APP_EXTERNAL_REPOSITORIES&lt;/code&gt; in .env.local file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REACT_APP_EXTERNAL_REPOSITORIES=~/repositories/my-test-repo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;and finally created a link
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ln -s ~/repositories/my-test-repo dashboard-ui/src/apps/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final considerations
&lt;/h2&gt;

&lt;p&gt;This approach is not a standard approach in JS/React applications/modules development, but allows me to have the advantages I have when I develop python applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every module is in it's own repository: different repositories might have different visibility, permissions, follow different merging strategies and have it's own wiki (or even different team);&lt;/li&gt;
&lt;li&gt;changes are picked up immediately by CRA without extra compile steps;&lt;/li&gt;
&lt;li&gt;the application is bundled from one single point (however, this is also a disadvantage in terms of CI/CD, but &lt;code&gt;node_modules&lt;/code&gt; can be cached to speed up build operations).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also some disadvantages, but for my pipeline they are not a problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;as mentioned, one change in a single repository requires the full application to be bundled again. A mixed approach can be adopted by adding the external repositories only in development leveraging &lt;code&gt;webpackEnv&lt;/code&gt; variable, building single modules with their own pipeline;&lt;/li&gt;
&lt;li&gt;setup for a new repository is not straightforward: we need to create a link and add the repository to an env variable (this might be automated as well), and we need to do this in order to build.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Can you see a simpler way to achieve this result? You think this is a terrible approach? Please share your opinion!&lt;/p&gt;

</description>
      <category>cra</category>
      <category>javascript</category>
      <category>webpack</category>
      <category>configuration</category>
    </item>
  </channel>
</rss>
