Sharing React Components Between an SPA and a Static Site
Tags: react, gatsby, javascript, css
Published: 2020-05-21 21:10:11

### How to share components between your React app and your Gatsby site.

SPAs and static sites are different and perhaps complementary approaches to building apps and websites. It’s quite common to see SPAs take the role of the app itself while static sites, known for their optimized speed and SEO, complement it with marketing sites, doc sites, blogs, etc.

Both approaches are commonly implemented using React and are quite often used together “in the service of a single cause” (e.g. an app and its doc site). When that happens it’s important to share and reuse their React components so that you keep a consistent UI across apps and sites and ship faster.

In this demonstration, I will be using [Bit](https://bit.dev) to share components between an SPA app and a static blog site, implemented with Gatsby.

[Bit](https://bit.dev) is a tool and component hub that makes it easy to publish and document components from any codebase. It offers both a CLI tool for isolating and publishing components and a place to host, document, and display them.

![Publishing components from the app and installing them in the blog](https://cdn-images-1.medium.com/max/2000/1*L18dgtI73soFPAOGufkGsg.jpeg)*Publishing components from the app and installing them in the blog*

## Demo — Share components Between CRA and Gatsby

1. Publish reusable components from “Bad Jokes” to my component collection on [Bit.dev](https://bit.dev)

1. Create a blog with Gatsby (the “Bad Jokes Blog”)

1. Use components from the “Bad Jokes” app in my new blog

### 1. Build a “Bad Jokes” app with create-react-app

For the purpose of this demonstration, I’ve built an app that serves bad jokes — you’re welcome to [check it out](https://bad-jokes-app.firebaseapp.com/).

    $ npx create-react-app bad-jokes

    // and then some coding...

![My “Bad Jokes” app. [https://bad-jokes-app.firebaseapp.com/](https://bad-jokes-app.firebaseapp.com/)](https://cdn-images-1.medium.com/max/2000/1*f5AmElWe6F5tOTdxaPKD7A.png)

Each component in this app is structured with its files under the same directory — it makes the component easier to share and reuse and simpler for your fellow component maintainers to find their way around it.

For styling, I’ve used CSS Modules to prevent “naming collisions” between classes, in future consuming projects.

    |-- components
      |-- Button
        |-- Button.jsx
        |-- Button.module.css
        |-- index.js
      |-- Card
        |-- Card.jsx
        |-- Card.module.css
        |-- index.js
      |-- Text
        |-- Text.jsx
        |-- Text.module.css
        |-- index.js
      |-- AppBar
        |-- AppBar.jsx
        |-- AppBar.module.css
        |-- index.js
      |-- BadJokesViewer
        |-- BadJokesViewer.jsx
        |-- BadJokesViewer.module.css
        |-- index.js

My app has four reusable components ([check them out in my collection](https://bit.dev/eden/badjokes)):

* [Button](https://bit.dev/eden/badjokes/button)

* [AppBar](https://bit.dev/eden/badjokes/app-bar)

* [Text](https://bit.dev/eden/badjokes/text)

* [Card](https://bit.dev/eden/badjokes/card)

### 2. Publish my app’s reusable components

I’ll first install Bit’s CLI tool globally on my machine:

    $ npm install bit-bin --global

Initialize a Bit workspace in my project’s root directory:

    $ bit init

I’ll then start tracking my components:

    $ bit add src/components/*

I’ll then install and configure a compiler for my components (after all, I don’t want them coupled to my app’s build setup):

    $ bit import bit.envs/compilers/react --compiler

It’s time to ‘tag’ these components:

    $ bit tag --all

I’ll then sign up to [Bit.dev](https://bit.dev), create a component collection, and log in from the terminal:

    $ bit login

It’s finally time to publish or “export” the components:

    $ bit export eden.badjokes

    // where 'eden' is the username and 'badjokes' is the collection name

**Done! A few things to notice:**

1. I’ve used prop-types and JSDocs to document and.. well, type… my components. Bit has read it and created docs for me. Bit also creates documentation out of React with TypeScript.

For example —

this:

{% gist https://gist.github.com/giteden/517f086a6a1a7e8999402795fc9889e9 %}

will produce [this](https://bit.dev/eden/badjokes/button):

![Example code rendered in Bit’s playground: [https://bit.dev/eden/badjokes/button](https://bit.dev/eden/badjokes/button)](https://cdn-images-1.medium.com/max/3576/1*IJBBXE_1d8bKIq014ceNrQ.png)*Example code rendered in Bit’s playground: [https://bit.dev/eden/badjokes/button](https://bit.dev/eden/badjokes/button)*

![Documentation presented in the component page: [https://bit.dev/eden/badjokes/button](https://bit.dev/eden/badjokes/button)](https://cdn-images-1.medium.com/max/2000/1*kvBifCHGQrjV3-p30nYfwA.png)*Documentation presented in the component page: [https://bit.dev/eden/badjokes/button](https://bit.dev/eden/badjokes/button)*

2. In the above example, you can also see the example code and the playground that renders it. Make sure to provide your component with an example — otherwise, it would not render in Bit’s playground.

With the examples, you will now have a reusable collection that [looks like this](https://bit.dev/eden/badjokes). You can use it in all your future apps too.

![](https://cdn-images-1.medium.com/max/2672/1*-FQm4rQrHNcwBlmmRe4q_Q.png)

### 3. Create a Gatsby blog site for my ‘Bad Jokes’ app

My app wouldn't be as successful as it is without a decent [blog](https://bad-jokes-blog.netlify.app/).

For this, I’ve used Gatsby with the gatsby-starter-blog starter:

    $ gatsby new bad-jokes-blog [https://github.com/gatsbyjs/gatsby-starter-blog](https://github.com/gatsbyjs/gatsby-starter-blog)

That’s how the blog looks ‘out-of-the-box’:

![](https://cdn-images-1.medium.com/max/2000/1*_vqvBuFzazYjEPqxQAHVsw.png)

I’ll now go to my new project’s root folder and install 3 components from my ‘Bad Jokes’ app:

    $ npm i @bit/eden.badjokes.button
    $ npm i @bit/eden.badjokes.card

Notice how each component is installed individually (as you would expect from independent components that are not coupled to a library).

Also, notice I’ve used NPM for that. These components are registered on Bit’s registry — not NPM’s. It is used here simply to perform actions.

I could also use yarn add or bit import for that.

It’s important to notice that when ‘importing’ using Bit, you actually do more than a simple ‘install’ — you “clone” a component into your repo, so that you may develop it and push new versions back to its component collection on [Bit.dev](https://bit.dev).

I’ll then use my installed component on this page to give it the same look and feel my ‘Bad Jokes’ app has:

<iframe src="https://medium.com/media/8ade038437056915edf2457fc14d8cc7" frameborder=0></iframe>

The result (with new content):

![My ‘Bad Jokes’ blog: [https://bad-jokes-blog.netlify.app/](https://bad-jokes-blog.netlify.app/)](https://cdn-images-1.medium.com/max/2000/1*DN4N2ozjgCUaAcxFDF959Q.png)*My ‘Bad Jokes’ blog: [https://bad-jokes-blog.netlify.app/](https://bad-jokes-blog.netlify.app/)*

{% github https://github.com/giteden/badjokes-blog %}

## Conclusion

As I’ve mentioned before — it’s time to face reality. It’s almost never enough to simply build a single app. We usually find ourselves in need of additional static pages — these pages are built in their own repositories, using a different set of tools, but they should all look and behave the same. By sharing components you enjoy a consistent UI — and — you build faster.