A Real-World React.js Setup for ASP.NET Core and MVC5

Comments 0

Share to social media

React is a set of JavaScript libraries for building the front-end User Interface (UI) for web and mobile applications. As well as being used by its creator, Facebook, it has also been adopted by Netflix, Airbnb, Yahoo and many more.

Because I’d worked on a Single Page Application (SPA) some years ago that used Backbone, I quickly appreciated that React and its related libraries was aimed at tackling the problem of building and debugging complex views with lots of interactions. (See What is React? for more detail.)

Existing front-end frameworks such as Backbone, Angular or Ember normally contain all the important components that are required to build a full SPA, such as models, views, controller and routing. React is different: React on its own only handles the rendering of views; showing data on the screen. To build a complete system with React, you need to gather other libraries in the React ecosystem. This React Ecosystem, referred to in this article as React+, includes related libraries that create a compatible system with all the necessary components for a working site, by performing the role of controller, routing and so on.

Why is React useful in ASP.NET?

The up side of React+‘s small library approach is that React+ is a very flexible system. This means you could just use React to drop in a single UI component on a MVC razor page, or go the whole hog and build an SPA by using the extra libraries available in the React+ world.

This flexibility allows the developer to pick the right UI approach for each specific user interface problem. Simple pages can use just normal Razor while more complex/intensive pages could use React, or Razor and React together.

I know from experience that this flexibility is very useful, because web development tends to involve two different types of pages: There are the simple pages for the purposes of login or admin that I churn out quickly using Razor with maybe help from a UI framework like Kendo UI. The second class of pages are the important customer-facing pages where I need a great user-experience with good design and exceptional response. Currently I use JavaScript, Ajax and HTML templating for these customer-facing pages, but I am planning to swap to using React in the future, hence this project.

Before I move on I should say that there is a down side of React+’s flexibility. I found it difficult, at the start, to understand and adopt React+ because there are so many different way to do things. For this reason I later wrote this article to help other ASP.NET developers understand and adopt React in their web or mobile applications.

One word of warning: React+ is still changing and articles and books get out of date. This article and open-source AspNetReactSamples on GitHub used React version 15.0.2 (see package.json for full list).

This article is about how to build and test React+ applications

Because this article is so long, I don’t have room to explain how React+ works in detail. However there are plenty of articles out there on React [ 1, 2, 3] but I would also really recommend the book “Pro React” which helped me a lot as it introduced each level of React+‘s sophistication in nice easy steps.

Note: In my review of the book on Amazon I said that the only down side of the Pro React book was it used Flux instead of the newer Redux library to implement stores. Well the author, Cássio de Sousa Antonio, replied and said he has made available an alternative version of Chapter 6 using Redux. How about that for good service!

I have recently taken Cássio’s new chapter on using Redux to heart and converted the ReactWebPack.Core sample project over to using Redux. You can read about my experience of doing that in my article ‘ Using a Redux store in your React.js application’.

Therefore I have focused on the tools and techniques that are needed to build and test React+ applications. The samples, which are available online, are designed to be scalable up to a real-world, production-ready applications with full build, test, and deploy capabilities. For this reason, these projects aren’t small and simple, but they do tackle the problems found in developing real-world application.

The features I needed were …

  • the ability to build one big SPA, and/or multiple small React components.
  • the ability to build a production, minified JavaScript files.
  • the ability to run the code locally and debug it.
  • the ability to Unit Test the React+ code, and debug it.
  • the build process must work on ASP.NET Core and ASP.NET MVC5.

Also I have gone to the trouble to share the decisions and problems I had in creating a template ASP.NET application that included React+. I did this so that you can understand not only how, but why I chose the options and what the alternatives are.

I will refer to the open-source Visual Studio solution, AspNetReactSamples , on GitHub which contains examples for both the new ASP.NET Core 1.0.0, the existing ASP.NET MVC5 and another approach using a NuGet package by Facebook, plus an example of how to Unit Test React.

1. For simple applications try ReactJS.Net

If you want a simple place to start with React on ASP.NET, then try the ReactJS.Net NuGet package from Facebook. This allows you to write JSX code which it turns into JavaScript on the fly. I have an example in my sample application called ReactJsNet.MVC5. (React.Net is also available for ASP.NET core RC1, but with a few limitations. See NuGet package ReactJS.NET MVC6).

Note: JSX is a source format that combines html and JavaScript. This sounds horrible, but it works, although you can write regular JavaScript if you like. Read this for an opinion on why it’s better to use JSX. More on the impact of using JSX later, but here is an example of some JSX.

If this React class Comment was called with the following JXS code …

… then the rendered HTML would be as shown below. Note that the method ‘marked’ is a library call that turns markdown into HTML, so “**bold**” gets turned into “<strong>bold</strong>”

Verdict on ReactJS.Net

ReactJS.Net is an easy introduction to using React+, but by default it uses the simple module linking of each library, i.e. using a global variable that other packages use, for example the way we often use JQuery in ASP.NET. In any substantial front-end system, this style of module-linking has its limits, and that is especially true with React because there are lots of libraries to include.

Therefore ReactJS.Net is a great solution if you want to add some simple React views to an existing ASP.NET project, or you just want to play with React. In my samples, the ReactJsNet.MVC5 project implements the React Quick Start Tutorial of a simple chat.

This is sufficient for a simple project, but for bigger applications, or those that need more React features such as stores and routing, we need a better way to handle the finding and linking of JavaScript module and libraries.

Note: You can use a system of linking modules on top of using ReactJS.Net, but then you need to use the more complex build process I describe in the next section.

However before we leave ReactJS.Net there is one feature that is very important – that of server-side rendering of React. This is really important as you can pre-render some React on the server and then tell the client-side React that the html has been pre-initialised and it will work with it. These sorts of application are called “Isomorphic Apps” (not a very helpful name in my opinion) but I don’t have the space to cover this.

Have a look at these articles [ 1, 2, 3] and chapter 8 of the “Pro React” book I recommended to find out more about “Isomorphic Apps”.

2. Building React+ applications with JavaScript modules

If you are familiar with .NET applications then you know that they consist of the code, e.g. C#, F#, VB,NET, you write and lots of libraries you call on to produce your final application. When you ‘build’ your application, the MSBuild process joins up the explicit references so that, when you call ‘Console.WriteLine()’, then firstly the right library, in this case mscorlib.dll, is included/available, and secondly the correct method in that library is called.

Now in larger, more complex, React+ applications we need to do the same thing in the JavaScript world. To do that I first need to know where to get the libraries from and then how to include the right libraries and link the explicit references.

2.a. Where to get the libraries from

In the JavaScript world there are a number of package managers, the biggest two being NPM and Bower. While I am a fan of Bower it soon became very clear that React+ uses NPM extensively. In the end it was obvious I needed to use ASP.NET’s package.json file and NPM, because Bower would not have given me the access to all the libraries I needed.

This one was more complicated and it felt like I had fallen down Alice in Wonderland’s rabbit hole! The build of a normal React/React+ goes like this:

  1. Transpile the JSX: Because I have chosen to use the JSX format then I need this translated that format into ordinary (ES5) JavaScript. This needs a Transpiler. I used Babel, which is well respected, but there are others, like Traceur from Google.
  2. Extract ES6 Modules: Because I am using the Babel Transpiler it understands the new ES6 module format which everyone in the React camp seems to use. Babel currently converts ES6 modules to a number of formats such as Common.js, AMD/Require etc. (Note: the ES6 module feature is at the time of writing not supported by any browsers natively, but is coming soon to Microsoft Edge).
  3. Load & link the references: React + libraries have lots of links to other libraries and it would be a real pain to have to hand-locate each library. There are a few ways to do this, but WebPack seems to be the way that most React developers use. There are a number of alternatives to WebPack.

Other Benefits of this process – ES6 JavaScript

If you are using a Transpiler then it makes sense to make the most of it. What most people do is swap over to using the new ES6 JavaScript standard which has a number of very useful enhancements. You have already heard about modules, but there are things like let & const and classes . Also many of the functions I used from the JavaScript underscore / lodash libraries like _.map() are built into ES6. The benefits are cleaner, more rigorous code and by using it you are somewhat future-proofing your code. Have a look at ” Top 10 ES6 Features every busy JavaScript Developer must know“.

Babel converts all the ES6 commands to regular JavaScript (ES5), plus has a babel-polyfill library so that the code will run on all the modern browsers. Babel can output code for older (ES3) browsers but you need to add some more settings and libraries (see this useful note about that).

Yes, swapping to ES6 does add to the learning curve but I didn’t find it that hard and having things like const and a properly scoped let variable is really nice, plus less typing for common things like functions (which I always mistype!).

The down side of this process – JavaScript ‘build’

The down side is that you have to ‘build’ the JavaScript, even in development mode. For anyone used to using JavaScript with ASP.NET MVC you know that it’s great to be able to debug JavaScript by simply editing the JavaScript, hit F5 in the browser and you are away. Now you need to run the build process on every change.

However there is one saving grace. WebPack has a “watch” mode and if you start this it will rebuild when you save a JavaScript/JSX file. A normal build takes some time, 6 seconds for my simple sample, but because WebPack caches the build then changing a single file normally takes ½ second.

Hang on, this sounds way too hard!

You might read all this about learning JSX/ES6, transpiling and WebPack and think this is just too complicated and it puts you off using React at all. That would be a pity.

Yes, it is more difficult and there is a lot of learning if you are coming from a classic (ES5) JavaScript background. However some of the things like the new JavaScript format and the new module format is coming soon to browsers (some features are already available), with some great advantages for the future (see this video on HTTP/2 and modules for instance).

As you read this article you will see I did struggle at the start, but on balance I have found it was well worth pressing on. The phrase people say about React is “give it five minutes” so do copy/Clone my examples, run them, have a look at the code and then decide if it’s for you.

2a. Setting up a build process

I would say that setting up the build process was the hardest and most frustrating part of the project. There are lots of different ways to set it up, each with its own advantages and drawbacks. The main problem, especially with WebPack, is to find out why something that should have worked didn’t. Let me tell you some of the decisions I made, so as to make this problem clearer:

Big decisions

  • I used Babel for my Transpiler. That is what everybody is using and it worked well.
  • I used WebPack for my module bundler because everybody else seem to use it. I found WebPack really hard work to configure but it works now. I have since heard about systemJs and jspm, which follow the ES6 module approach. I am definitely going to look into those.
  • I chose WebPack as the command to call for the build process because it has a ‘watch’ facility to recompile whenever the contents of a file changes. I think that is best, but you can call Babel, which then calls WebPack.
  • I chose to write NPM “scripts” to call WebPack. These scripts live in the package.json. I quite like this, and it works for Unit Testing too (see later).
  • I chose to use the NPM Task Runner extension to call these scripts in Visual Studio, and the VSCode npm Scripts extension to run them in Visual Studio Code (more on that later). I tried other approaches such as the WebPack Task Runner, but NPM definitely worked the best.

Small decisions

  • I chose to use the extension ‘.js’ for my JSX code rather than ‘.jsx’. A lot of people do that and the tools handle either. There isn’t much in it, but if you use .jsx then when you use the module import you have to add ‘.jsx’ on the end of the filename. (Note: the build files in the sample applications are set to ONLY look at .js files).
  • This is a bit deep so ignore until you understand WebPack, but I didn’t use WebPack’s dev server to deliver the bundles files in the development build. This was partly because I had problems with setting up sourcemaps but I also liked having the bundled JavaScript file around to look at. However I did use WebPack’s dev server in the Unit Testing, for no better reason than it worked that way by default.

To see other people’s approaches to the React build process, some of which I learnt from myself, especially the first one, then do look at:

2b. How to run the build process

The best way to study my build process is to download the AspNetReactSamples and run a build. There are two versions which build and run the same React application, but for the two current version of ASP.NET MVC:

  1. ReactWebPack.Core, which is built on the new ASP.NET Core (1.0.0) MVC app.
  2. ReactWebPack.MVC5, which is built on the existing ASP.NET MVC5 app.

The full information on how to do this is in the Readme.md file in the AspNetReactSamples solution so I won’t repeat it here.

Note: One nice trick is to use Visual Studio Code (VSCode) alongside Visual Studio. If you aren’t aware of VSCode it’s a free, lightweight IDE which is especially good with JavaScript etc. In fact I found that VSCode understands JSX format better that Visual Studio 2015. I find myself developing with both VS2015 and VSCode open: VS2015 for the C#/ASP.NET parts and VSCode for the React parts. There are details in the Readme file on how to set this up.

3. Unit Testing

One of the plus-points of React/React+ is that it is easy to Unit Test for two reasons. Firstly it is easier because Reactuses what is called a ‘ Virtual Dom‘, which is an in-memory DOM. The Virtual Dom means that the Unit Tests tools can check the virtual Dom rather than the actual DOM, which can be slow and troublesome. The second reason is that Facebook, and other React+ library suppliers like Redux, have thought about Unit Testing from the start and made sure their components/libraries are easy to test.

Even so, it took quite a bit of research and trials to set up a sensible Unit Testing environment. Let me tell share with you the choices and decisions I made so you can understand why I went this way:

Big decisions

  • I chose Mocha as my test framework. Facebook recommend Jest for Unit Testing React, but a number of posts [ 1, 2, 3] said Jest was slow and Mocha was better. I have also used Mocha successfully in the past, which gave me confidence in this approach.
  • I used Karma as my test runner. It’s popular, and I have used it before. Specifically it has a ‘watch’ facility and can interface with WebPack, which means it does a recompile and test when a test file is changed. That feature makes a big difference to the test/fix cycle.
  • I run my Unit Tests inside a real browser, Chrome, rather than a phantom browser. This adds a bit of start-up time but it does mean I can debug my Unit Tests (I talk about that later).
  • I used AirBnB’s enzyme React testing utility. I had lots of trouble with my early tests, mainly because I copied an old version, but it was obviously not easy. The React Test Utilities page suggested Enzyme which I found easier than the standard React Test Utilities, and Enzyme has good documentation. I do recommend you look at this.
  • I used mJackson’s expect assertions rather than the older expect.js library I used before. mJackson’s expect has shorter test names and has its own event spy part. The spy part is significant because it turns out that Sinon, the normal package for doing spying on events, has some problems with WebPack.
  • I placed my Unit Tests in another Visual Studio project, mainly because I want to keep my test code separate. UPDATE: It turns out that placing the Unit Tests in another project was a bad idea. The problem is you get the ‘multiple copies of React‘ error in some cases. I therefore have moved the JavaScript Unit Tests into the ReactWebPack.Core project.
  • I created NPM scripts in the ReactTests’s package.json file so that the tests could be run in same way as the build. That way I can call them for Visual Studio or VSCode. I tried other ways but this was certainly the best.

I have only done a limited amount of Unit Tests (only 5 Unit Tests at the moment). UPDATE: I’ve done a lot more work on Unit Testing – have a look at Adding mocking to React.js Unit Tests and Unit Testing React components that use Redux. Only a real application will tell me whether I have the right setup (my Backbone SPA had over 700 Unit Tests), but I am becoming more confident on the Unit Test set up in these samples.

However there is stacks of information on Unit Testing React+, because lot of people, such as Facebook and Airbnb, use Unit Tests. Try:

3b. Running the React Unit Tests

Again, if you want to look at the Unit Tests, I recommend you download the AspNetReactSamples solution and look at the ReactWebPack.Core project. There are two files in the top directory, karam.config.js and tests.webpack.js, which control the Unit Tests, with certain libraries added to the package.json file. The actual Unit Test code is in the directory JsUnitTests directory. The Readme.md file in the AspNetReactSamples solution has all the information for running the Unit Tests, so I won’t repeat that. However here are some thoughts on Unit Testing React.

Debugging with Unit Tests

You can run the Unit Tests once by calling the command test-run. It will tell you what passed or failed. However when you do have a failing bug it is very useful to be able to debug it by inspecting the code and live variables, changing the code and retesting. Therefore I have added a test-watch that first runs the tests, but leaves the browser open and then will rebundle and rerun the tests if a .js file is changed.

Because the test-watch command leaves the browser open, you can use Developer Mode (F12) to place breakpoints in the code and rerun the tests by pressing F5 in the browser. Then you can inspect the code and the live variables to see where the problem is.

However because we are working with JSX and a Transpiler there is a wrinkle!

The issue of transpiled code

By default Chrome will find the source maps and show you the original JavaScript/JSX file. This is really helpful, but can be misleading as you aren’t looking at the actual code that is running. Mostly it’s fine, but imported methods/variables will have different names in the Chrome ‘scope’ window from what you see in your original code.

If you want to see the underlying ES5 code then the only way I have found to do that is to turn off ‘Enable JavaScript source maps’ in Chrome’s developer setting and press F5 again. Then you see the real code, which shows the correct variable names.

Once you get used to it it’s fine, but I got very confused at the start.

Note: Mocha has some useful commands when you are working on a large set of tests. The most important is the .only() method which, if added to a test/sub test, will tell Mocha to only run that specific test. Also the .skip() method can be added to a test/sub test and causes it to be skipped.

Another useful feature is adding the line debugger; to your JavaScript which will cause a breakpoint when it is executed if the developer tools (F12) is open.

Conclusion

I started this project by using cut-and-paste solutions that I found on the web and got terribly lost, especially because some components such as WebPack can ‘fail silently’, in that it does not do what I want it to do, but does not produce any error messages. Therefore, when I wrote this article, I took the time to include the decisions I made and why I when that way. I hope that helps you to decide what you want to do, and more importantly help you understand what is wrong when it doesn’t work.

This has been quite a long research project for me, but at the end I have what I consider a really good example setup that I could use in a real project. My final solution ticks almost all the points I needed apart from having multiple React apps (but I know how to do that).

My journey with React continues and there is much more to learn. I hope this helps you on your evaluation and possible use of React as well.

My journey with React continues. I have written a new article called ‘Using a Redux store in your React.js application‘ where I talk about how I altered the React part of one of my samples, ReactWebPack.Core, to use Redux. I explain the advantages of using a store like Redux and then detail the steps needed to switch your React application over to using Redux.

Load comments

About the author

Jon P Smith is a full-stack software developer and architect who focuses on Microsoft's ASP.NET web applications using Entity Framework (EF) ORM on the server-side, with various front-end JavaScript libraries. Jon is especially interested in defining patterns and building libraries that improve the speed of development of ASP.NET web/database applications. As well as his articles on Simple-Talk Jon has a number of extra articles on own technical blog, www.thereformedprogrammer.net, and has produced a number of open-source libraries.  He is also the author of the book called Entity Framework Core in Action, published by Manning.