alvinashcraft
shared this story
from Simple Talk RSS Feed.
React is a front-end user interface library developed by Facebook, originally to help them improve their own site. Since then it has grown into somewhat of a phenomena, with many active users. In this article, Jon Smith provides multiple examples of how to use React with recently released ASP.NET Core MVC, and the existing ASP.NET MVC5 framework.
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
Why React?).
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.
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.
Note: 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 RC2
, 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
s
erver-
side rend
er
ing
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.
2.b. How to include the right libraries and link the explicit references.
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:
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.
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).
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:
ReactWebPack.CoreRC2, which is built on the new ASP.NET Core (RC2) MVC app.
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. In fact 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
React
uses 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. However others normally have the tests in the same project, which has the advantage of only one package.json to keep up to date. You can decide which you like.
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) so I can’t be sure that this is a perfect setup, but it looks good. Only a real application will tell me whether I have the right setup (my Backbone SPA had over 700 JavaScript Unit Tests).
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
ReactTests project. 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. 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.CoreRC2, 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.
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.