Dataverse Web Resources with React, Typescript and FluentUI (_neronotte's way)
Tags: powerplatform, webresources, react, typescript
Published: 2024-07-06 20:36:27

In a world that moves towards _Custom Pages_ and _PCFs_, there are still scenarios in which a old, simple, custom _WebResource_ is the best choice.

[Diana Birkelbach wrote a really interesting post about this topic](https://dianabirkelbach.wordpress.com/2021/09/29/goodbye-html-web-resources/) describing pros and cons of both, and also describing how to mix them together to enrich the user experience.

It's 2024, and the best way to create custom WebResources for Dataverse is to leverage React, Typescript and FluentUI, for many reasons:

- Continuity with Dataverse internal UI engine
- Continuity with PCF development
- UI automatically styled like Dataverse
- Automatic support for themes
- Strongly-typing & compile time errors

... and many more.

There are a lot of interesting articles and videos online on how to create _WebResources_ leveraging those techs, and I don't like to repeat stuff that's already available (I'm lazy, you know it), thus you will find a few references at the end of this article. Today I'm gonna show you how I like to work on this stuff.

## Let's start

### Prerequisites

To work with react + Typescript + FluentUI, be sure to have the latest version of **Node.js** and **NPM** installed on your local machine. [This doc shows you how to setup both](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm).

### Initial folder setup

First of all, I like to start setting up the folder that will contain all my WebResources (images, html pages, javascripts, and so on). For the sake of this tutorial I will store everything under `c:\sources\test\WebResourcesMyWay`. [I like to do it via PACX](https://github.com/neronotte/Greg.Xrm.Command/wiki/pacx-webresources-init):

```Powershell
pacx webresources init
```

![pacx webresources init](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lxo1wor9qhzl641hswqn.png)

It initializes my WebResources folder with the following structure:

![Folder structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uycuwu0rfekehuv4k9m0.png)

The folder names are self explanatory. They will reflect how WRs will be named within my Dataverse environment.

## A custom home page 

Assume we would like to create a Dataverse WebResource that acts as home page for users accessing one of our model driven apps.

Let's setup our React + Typescript + FluentUI project. On the root folder, let's type:

```Powershell
npx create-react-app home --template @_neronotte/cra-template-dataverse-webresource
```

This command will create our WebResource project folder called `home` with the following structure:

![Project structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l55lpdsegua02x3xxt6j.png)

It generates a React+Typescript App project with:

- [sass](https://sass-lang.com/) to handle CSS on steroids.
- [@types/xrm](https://www.npmjs.com/package/@types/xrm) to manage Dataverse client API using strongly typed classes.
- [ClientGlobalContext.js.aspx](https://learn.microsoft.com/en-us/power-apps/developer/model-driven-apps/clientapi/reference/getglobalcontext-clientglobalcontext.js.aspx) automatically referenced in the `index.html` page (you can remove it manually if your web resource needs to be opened within a form).
- Webpack already configured to generate a single JS file without chunks.
- A ready-to-use local stub for Dataverse client API that can be used to test the WebResource locally, simulating server calls (under the `src/sdk` folder).

There are a few manual operations to complete before starting, that are described in the generated `README.md` file.

I need to:

1. Change the value of the **title** tag of the `./public/index.html` page to provide a meaningful title for the webresource.
2. in the `config-overrides.js` file, replace `<output path>` with `../ava_/pages/home` (where I want my WebResource to be saved).
3. in the `package.json` file, replace `<output path>` with `../ava_/pages/home`.
4. If needed, in the same `./public/index.html` page change the relative url of `ClientGlobalContext.js.aspx` page to match our project structure. In my case, the compiled React app will be placed into `ava_/pages/home` folder, thus the default `ClientGlobalContext.js.aspx` path works fine.

Once done, everything's ready for our WR to be compiled and run. Just type:

```Powershell
cd home
npm run build
```

And you'll see that the current content of the WR is compiled and placed in the `ava_/pages/home` folder.

![WebResource build output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2djztiv4zc4o0sbgcs28.png)

Now, if you type:

```Powershell
npm run start
```

The WR starts in a new browser window.

![Sample WebResource](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vi1gxn454gqykj3d9knu.png)

You can now change the contents of the WR starting from `App.tsx`, and **Node** will recompile on the fly and reflect the changes in the browser window.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ak0eayzfqwrgyl86hojb.png)

You are now ready to go, happy pro-code development!

## References
- [@_neronotte/cra-template-dataverse-webresource](https://www.npmjs.com/package/@_neronotte/cra-template-dataverse-webresource)
- [The LinkedIn post that shows a first use of @_neronotte/cra-template-dataverse-webresource](https://www.linkedin.com/posts/riccardogregori_dynamics365-react-typescript-activity-7117118675152756737-pfNY?utm_source=share&utm_medium=member_desktop)
- [This is a tutorial on React App Rewired](https://egghead.io/lessons/react-customize-create-react-app-cra-without-ejecting-using-react-app-rewired), that seems to be the easiest way to generate build that can "work" in a Dataverse environment.
- [Tutorial on how to create custom webresources from scratch](https://butenko.pro/2020/04/22/development-of-custom-html-js-webresources-with-help-of-modern-frameworks/) it shows how to properly modify webpack.config.js