Using React.JS as a Micro Frontend in Blazor WASM
Tags: dotnet, microfrontend, javascript, react
Published: 2022-01-28 20:23:11

## Table Of Contents
* [Disclaimer](#disclaimer)
* [Configuring the Projects](#config)
* [Integrating the Micro Frontends into the App Shell/Startup Application](#integration)
* [Automating the Build Scripts](#automating)
* [Installing and Setting Up React.JS](#react)

## TL;DR

Here is a link to the github repository. Feel free to clone, download or fork and make PRs.
https://github.com/XanderSelorm/MicroFrontendsExample

## Disclaimer <a name="disclaimer"></a>

Kindly note that this tutorial is for educational purposes only and that this set up or architecture has not been tested in a production environment yet.

In our [previous part](https://dev.to/xanderselorm/implementing-micro-frontends-using-net-blazor-wasm-55bl) of this series, we looked setting up the environment and folder structure for the Micro Frontends.

## Configuring the Projects <a name="config"></a>

### ReactMicroFrontend Project

Since the `ReactMicroFrontend` is basically a JavaScript project, NPM will obviously be used as the default package manager.

To initialize NPM in the `ReactMicroFrontend`, using the terminal, ensure that you are in the root directory and you have Node.js and NPM installed globally on your computer. If not, download it from [here](https://nodejs.org/en/download/). Then continue by running the following command in the root directory of the project:

```cs
npm init
```
Since this project is for tutorials purposes only, we'll keep the default values when initializing NPM here.

With that done, let's look at how to bundle out JavaScript codes.
 Since we're setting up the React Library manually, let's decide on what our bundler will be. For the sake of this tutorial, ‘Parcel’  will be used instead of usual webpack for the bundling of the React application.

Now that we have npm installed and initialized in our project, let's use it to install Parcel. If you want to know more about `Parcel`, [check it out](https://parceljs.org/docs/).

Run the following command in the root directory of the MicroFrontend (React) project in question:

```cs
npm install parcel --save-dev
```

Now that this is done, let's determine where our React code will be bundled to upon build.

* Open the `package.json` file in the `ReactMicroFrontend` project and modify the following lines:

```json
{
  //destination path
  "main": "wwwroot/dist/app.js",

  //origin path
  "source": [
    "src/index.jsx"
  ],

  //scripts
  "scripts": {
    "build": "parcel build src/index.js",
    "clean": "del-cli wwwroot/dist/* node_modules",
  },
}
```

When you take a critical look at our `clean` script, you'd realize the use of a package called `del-cli`. This package is used for permanently deleting files and directories. This packages needs to be installed globally before it can be used.
Run the following command in your terminal to install it: 
```cs
npm install --global del-cli
```

### MicroFrontendExample.Shell Project

Awesome! With that done, save the file and let's look at how to make sure our JavaScript code from our MicroFrontend is also bundled into the App Shell/Container App.
To do this, we'll have to go back into the directory of our App Shell/Container App and then run a few commands.

In the startup application, ‘Webpack’ will be used to bundle all the JavaScript frameworks together into the main application/App Shell. And since we'll be using NPM here too, we'll initialize NPM in this directory too and then install the Webpack. Use the following commands by running them in the root directory of the startup project/App Shell:

Don't forget to keep the default values for NPM. (Well, you can still go ahead and customize it if you wish)

```cs
npm init && npm install webpack --save-dev && npm i -D source-map-loader && npm install --save-dev webpack-cli
```

If the above commands fail, run them one after the other, like so: 

```cs
npm init
```

```cs
npm install webpack --save-dev
```

```cs
npm install --save-dev webpack-cli
```

...and then

```cs
npm i -D source-map-loader
```

## Integrating the Micro Frontends into the App Shell/Startup Application <a name="integration"></a>

* In the Startup Project’s ‘App.razor’ file, we'll load the entry-files of the class libraries (micro frontends) as assemblies.

Do this by adding the following lines of code to the `App.razor` file:

```cs
@using System.Reflection

<!-- Default File Content -->

@code {
    private List<Assembly> LoadedAssemblies = new List<Assembly>()
    {
        typeof(ReactMicroFrontend.App).Assembly
    };
}
```

* In the same file, on the `<Router>` tag, add the `AdditionalAssemblies` attribute and assign the `LoadedAssemblies` value to it. 

```html
<!-- AdditionalAssemblies="@LoadedAssemblies" -->
<Router AppAssembly="@typeof(Program).Assembly" AdditionalAssemblies="@LoadedAssemblies" PreferExactMatches="@true">
```

* In the Startup Project’s `_Import.razor` file, add the namespaces of the various micro frontend applications in order to make them available throughout the startup project:

```cs
@using ReactMicroFrontend
```

Awesome! A couple of things more to do...

* Let's begin by modifying the `package.json` file over here too. we'll add the `build` and `clean` scripts to the `scripts` object. 

```json
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "clean": "del-cli wwwroot/dist/* node_modules"
  },
```

Now, let's add the configurations for `webpack`. We'll do this by adding a new file and name it as `webpack.config.js`.

* Right click on the project > Add > New item > Javascript File.

* Change the name to `webpack.config.js`, and click Add.

![Adding JS File](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dxsuo243ilqumjnrosu9.png)

In the `webpack.config.js` file, add the following block of code, customize it if the need be, and save it.

```js
const path = require('path');
const fs = require("fs");

module.exports = [
  {
    name: "get-react",
    entry: () => fs.readdirSync("../ReactMicroFrontend/wwwroot/dist/").filter(f => f.endsWith(".js")).map(f => `../ReactMicroFrontend/wwwroot/dist/${f}`),
    devtool: "source-map",
    mode: "development",
    output: {
      filename: "app.js",
      path: path.resolve(__dirname, "./wwwroot/dist/react/")
    },
    module: {
      rules: [
        {
          test: /\.js$/,
          enforce: "pre",
          use: ["source-map-loader"]
        }
      ]
    }
  }
]
```

* Finally, let's make sure that our React script is added to our `index.html` file. If not, before the closing `body` tag in the `index.html` file, add:

```html
<script src="dist/react/app.js"></script>
```

## Automating the Build Scripts <a name="automating"></a>

If you've read up to this point, congratulations! This is the last step and then we'll take out app for a test ride 😀!

By now, I'm sure you are wondering whether we'll be calling the build scripts manually for each project? The answer? Hell no! 😀 We'll automate that too. So that when the build command is called for the dotnet projects, that of our JavaScript microfrontends are called too.

Let's look at how to implement that:

* We'll edit the project files of both the `MicroFrontendExample.Shell` and any of our microfrontend which uses JavaScript code; this includes out `ReactMicroFrontend`.

If you're using VS Code, it's easy to locate the project files. 

But when you're using Visual Studio, right click on the project > Edit Project File.

* Before the `</Project>` closing tag, add the following block of code:

```html
<Target Name="npm restore" BeforeTargets="BeforeBuild">
        <Exec Command="npm install" />
</Target>

<Target Name="webpack" AfterTargets="Build">
	<Exec Command="npm run build" />
</Target>

<Target Name="webpack clean" AfterTargets="Clean" Condition="Exists('node_modules')">
	<Exec Command="npm run clean" />
</Target>
```

Awesome! Congratulations for making it up to this point! Now we're free to build our application. :D 

Ooopss!! There are Errors!?? Chill bro, 😀, this error was expected. 😊
This error occurred because we directed the `Parcel` bundler to an `index.js` file which doesn't exist. This is because we haven't installed and set up our React.JS yet. 

This brings us to our next and final topic:

## Installing and Setting Up React.JS <a name="react"></a>

This final step should be fairly easy to do. We'll run a couple of commands, run a few lines of code and then we call it one hell of a guide! 😀

* To begin, let's install react and react-dom. Run the following command in your terminal:

```cs
npm install --save react react-dom
```

* Secondly, let's create a new file, name it `index.js` in the `src` folder.

* Add the following code block to the new file you created:

```js
import React from "react";
import ReactDOM from "react-dom";

window.renderApp= () => {
  const domElement =
    document.getElementById("react-app") ||
    document.querySelector("#react-app");

  if (domElement) {
    ReactDOM.render(<h1>Hello, React🌐!</h1>, domElement);
  }
};

```

* Finally, feel free to run the application, navigate to "/ReactMicroFrontend",  and experience the power of Blazor!

Your final app should look like this:

![Final Cut](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ajbciak4txuwh7egr0cu.gif) 

Here is a link to the github repository. Feel free to clone, download or fork and make PRs.
https://github.com/XanderSelorm/MicroFrontendsExample

Thank you very much for reading. Follow me for more interesting guides and content. And oh, don't forget to leave a reaction 😉. I'll be grateful 😊 

See you later, cheers!