Making a create-react-app project in .NET

In my last post I discussed how to install Episerver Quicksilver site. As I note there, there’s a license cost to using Episerver, but the techniques I discuss below can be applied to any ASP.NET MVC 5 site.

A create-react-app .NET web application project

We’ll create a new .NET web application project to place the create-react-app project’s files in. We won’t compile a website there, but simply hold our create-react-app project (sort of like the node.js project type that Visual Studio offers you as a project template). 1 2

Visual Studio Create Project Dialog

The project should be empty with no authentication, folders, references, or tests.

Visual Studio Create Project Dialog 2 with no authentication

Installing create-react-app

Init new project

We’ll install create-react-app globally so we can use it to create new empty react projects. This is analogous to using Visual Studio to create new .NET projects. We’ll place the react project in the solution folder (next to the quicksilver Sources folder) for now. 3 4

Command line showing npm install of create-react-app

Move files to .Net project

Move all the files from the create-react-app directory into the new project and remove the empty directory create-react-app introduced.

Go back to VS and show all files for the VS project we created above. Include the src and package.json files.

Start create-react-app

At this point, you should be able to cd to the new project and start the create-react-app application.

homepage of create-react-app showing react logo and some text

Building a create-react-app project

The create-react-app contents are there to serve the complete react SPA. However, the only parts we’ll use in the Epi site are the js and css created for our components. The dev server that create-react-app launches serves the js by running webpack to generate a transpiled file of all your js. It does this in memory and serves it from the virtual path

~/static/js/bundle.js. Then, when you’re ready to deploy running

creates a webpack build optimized for production and sticks it in the build/static/js folder of the create-react-app project with a the name main.[hash].js (where [hash] is a hash computed from the file’s contents).

Our plan for production

The trick we want to pull off is to always use the path static/js/bundle.js. That way, we can reference that virtual path in our MVC project in both development and production scenarios. Using the proxy in development, the express server that serves ~/static/js/bundle.js will serve the in-memory bundled code. When we go to production, we need to rename the main.[hash].js file to bundle.js and stick it in the website’s /static/js/ folder.5

A proxy for Quicksilver with SSL

The point of a proxy is that we want webpack-dev-server to reload our bundle.js whenever we save our js code, but we want all other requests to be handled by our ASP.NET site.

Configure the proxy

Add the new member “proxy” to the package.json file created by create-react-app. The proxy will serve the bundle from the path /static/js/bundle.js, but will proxy requests to the quicksilver site for everything else:

Run npm start again, start the quicksilver site in VS, and manually enter the url

localhost:3000/Login

You should see the login page for the quicksilver site being proxied through the express server create-react-app has started.

Quicksilver homepage with url showing proxied through dev server

Using SSL

Note, however, that we’re not using ssl. To allow ssl, we need to tell create-react-app to use HTTPS. Add a file .env.development that holds environment variables to pass to the server create-react-app starts:
creation of an empty file for the development environment

In the file, place the single environment variable assignment:

Start the react app again and observe that your computer doesn’t trust the certificate. Copy it to a file and import it into Trusted Root Certificates. (Note that this is a somewhat dangerous for your development environment. An attacker with this certificate can use it to create certificates that your computer will trust. For this reason, the certificates only have a 1-month lifetime before they expire. You’ll need to re-import the certificate when it gets recreated by webpack-dev-server after that. Make sure to delete the exported certificate when you are done. Restart your browser to see that the new certificate is trusted

create-react-app homepage with trusted certificate

Now, we can update our proxy config to use SSL. If we change the express proxy to use https, and the Quicksilver proxy to use https, however, it still fails, because express doesn’t trust the ssl setup by IIS Express. Add the option “secure”: false to disable leaf validation because we the express server doesn’t trust the iis express ssl.

Now, we can log into the Quicksilver site using the proxy and we should see the .AspNet.ApplicationCookie and, if we’re an admin, the epi quickNavigator:

homepage of quicksilver with epi tool and application cookie

Redirecting Default

There’s one more problem: we can’t get to the Quicksilver root homepage through the proxy, because react is serving the app from there (and it ignores attempts proxy the root). Add a path rewrite object with the path ^/default redirecting to /:

Now you can browse to /default to get the Quicksilver homepage.

quicksilver homepage accessed through proxy with alternative url /default

Adding our app to MVC

From here we could reference the bundle from quicksilver and display some react components by adding a div with id="root" and the script reference to /static/js/bundle.js to our homepage view:

We reference the bundle in the location that the proxy server serves it from, and the div gives react a place to put the app on the page.6

quicksilver homepage with react component

To demonstrate that auto-reloading is working, modify the component and save the file. Note that your changes are displayed without manually refreshing the page.
modified create-react-app component


Category:

Leave a Reply

Your email address will not be published. Required fields are marked *