What do you want to learn?
Skip to main content
Beyond ASP.NET MVC: Modern Web Development Demystified
by Chris Jones
Making an ASP.NET web app used to be so simple. This course will walk you through recent developments in web technologies so that you can choose which ones are relevant for you to learn.
Start CourseBookmarkAdd to Channel
Table of contents
Introducing the Demo Application
Throughout this course we're going to be referring to a conference planner demo application. It's a very simple application that looks like this. It simply has a list of conferences, and for each conference there's a link where you can click to say that you're going. When you click the link an Ajax call is made to the server using JQuery. The code itself is a very small example of a very typical ASP.NET MVC application. We've got a Razor view, which does a foreach to the conferences and renders the details out to the page. In the Global.asax we've got a standard ScriptBundle using the ASP.NET script bundling system, and we've got a custom LessTransform, because in this application they've chosen to choose less as a CSS transpiler. In terms of controllers, there are two. This application has the HomeController, which renders the main page, and it has a ConferenceController, which has a server side that gets called when you click on the link. There's also some custom JQuery. If we look in our Scripts folder we have an Ajax helper class, and we have an index.js, which contains the code that runs on our index page. So, a very standard ASP.NET MVC application, and throughout this course we're going to gradually improve it with new technologies, and you'll be able to see how that makes the application more maintainable.
Getting Dependencies Easily with Package Managers
In this module we're going to talk about package managers. Now, package managers are an essential concept to get your head around as we'll be using them throughout this course. And by the end of this module you'll understand how they can help you to manage your app dependencies and you'll wonder how you ever lived without them. So, what are we going to talk about in this module? Well, we are going to ask, what are package managers? Why do we need them? What is Node.js, and what does it have to do with any of this? And then we're going to talk about a few front-end package management tools, so that's npm, Yarn, and Bower.
Why Package Managers?
So, to understand the main benefits of using a package manager, it's probably best to start by looking at how we would add a third-party library to our application without one. So, the classic approach to adding a third-party library would be, you find the right website, find the download link, download the files locally, review the dependencies. So, for example, if I was downloading a red-stripe library that allowed me to add red stripes to our website, I'd need to check, okay, does this library depend on jQuery, for example, and if so I'd have to repeat the process for each dependency. So I'd have to go and find jQuery's website, find the download link, and check the versions as well. And that's an important thing. So I'd have to check my red-stripe library requires that this version of jQuery, you know, have I already got that version of jQuery, is my version too old, too new, I have to look into all those things, and I have to do all that manually. And the same applies if I wanted to check for updates. So if I want to see, are there any updates available for the red-stripe library, or for jQuery, and will they be compatible with each other, I'd have to do all those checks manually, and go back, and download the files again, and put them in my solution. All of that, takes a lot of manual effort. So, how does this work with a package manager? Well, I ask the package manager to install the package. For example, I would ask it to install the red-stripe package. It will go and find the files and download them automatically for me. And it will also go and find and download any dependencies automatically as well. So in this example, if it depends on jQuery, the package manager will automatically go and find a compatible version of jQuery and download that for me as well. And equally, updates can be found and installed automatically too. So I can ask the package manager, check if there's any updates of these packages, and if there are, it will download them, install them, and make sure that they're still compatible with the versions of the dependencies, and update the dependencies if necessary. So you can see that by using a package manager we're avoiding a lot of manual effort, and the package manager is doing a lot of the grunt work for us. So, which package managers are we going to talk about? Well, we'll mention NuGet quickly. If you're a .NET developer you're probably already using it, it's the .NET package manager that provides all the benefits we were talking about, but for your server side .NET assemblies. But in this course, we're going to focus on three front-end package managers, so that's going to be npm, Bower, and Yarn. And these three all run on top of something called Node.js.
What is Node.js?
NPM and Semantic Versioning
So, let's talk a bit about the Node Package Manager. So, as we said, it's included with Node.js, so when you install Node.js you get npm along with it. And it allows you to install packages either locally or globally. And this is important because locally means that the package is installed in a particular directory to go along with the particular project. So, for example, I'm working on a website, I might install a package like jQuery locally, within that website's folder, because that website requires jQuery, but also npm allows you to install things globally. And this is quite useful for build tools, and things like that, because it allows you to install it once on that machine, and then every application on that machine has access to the tool. So, npm uses a file called package.json to record which packages are installed for your application. So, for example, if I start using in my website folder, it will create a package.json file and that file will list all of the packages that are currently installed, and which versions within my application. Similar to the way the NuGet works with the package.config file. It uses something called semantic versioning for version matching. And we can have a look at what that means in a second, but it's one of those sort of questionable default behaviors that have led some people to become a bit unhappy with npm. There's another behavior, for example, where you have to specify a particular command-line switch when you install a package to make it update your package.json file. If you don't do that it won't update the package.json file, so you end up with a dependency there, but no record of the fact that it installed a dependency. So there's a couple of sort of questionable default behaviors, which probably made sense when they first released npm, but in the years since, now that it's commonly used on big teams, and within big organizations, these issues have sort of started to cause a bit of problem for teams working with npm. Let's have a look at semantic versioning and how it relates to npm. So if you haven't heard of semantic versioning, it's the standard that was introduced a few years ago to try and combat the inconsistency that different library authors used in how they handled their version numbers. So you'd get some people who'd increment the major version on every release, some people would increment the minor version every release, some people would increment the patch, you never really knew if a version number went up, or if one part of the version number changed, what did that actually mean? So semantic versioning was an attempt to try and standardize that. And npm follows semantic versioning in the way that we configure the version number and the config files. Npm allows us to use different characters in our version definitions to tell it how to behave when it downloads those packages. So, for example, if I've just got the source code of this project onto my machine, and it includes this package.json file, and I tell npm to install the packages, it will go off to the internet and it will find the exact version of core-js : 2.4.1 only. It will find the latest patch-level release of Gulp. So that means it will find the latest 3.9.x, so I might get 3.9.1, I might get 3.9.5, whatever the latest patch level is. With jQuery it will find the latest minor-level change, so that'll be the latest 1.x. So I might get 1.11, I might get 1.12, I might get 1.15. And the asterisk specifies that it will just get the latest version, whatever it is. Now, the hat symbol is the default, and this has caused some problems with npm because the idea here is that the hat symbol allows npm to get the latest minor-level updates, which according to sematic versioning that means the latest new features that have been added, but without the breaking changes. So it won't increment the major version number because that's the only version number that's allowed to introduce breaking changes. But of course, in reality, many library authors accidentally introduce breaking changes, introduce regression bugs into minor patches, and therefore, this behavior by default has caused teams problems because one developer will run npm to install the packages and they might get jQuery 1.12, another developer ran it earlier so they got 1.11, and jQuery 1.12 accidentally introduces some sort of regression bug. And then you've got one developer who's getting the bug on their machine, another developer who's not getting the bug on their machine, it all becomes very difficult to manage. So the recommendation with npm is to use the top option, to not use any character at all and fix it to that version only.
Demo: Installing an NPM Package
Okay, so I'm going to show you how to set up the npm, Node Package Manager, for the first time, and we're going to install the package. To do this, we're going to come to the ConferencePlanner sample application that we saw in the overview module. And, you can see here that this application is just including jQuery manually from a download that somebody's done at some point in time. It's not using any of the front-end package managers. So, let's change that so that is uses npm supporting the jQuery library. So I've got a command prompt here, and this is in the folder of the ConferencePlanner application. So the first thing I need to do to enable this to work with npm is just type npm init. This now gives me some prompts where I can enter information about the application. Now, for example, the first field here is name, and we have to put it in lowercase. The name doesn't matter too much, nor does the version or description in our case, so I'm just going to press Enter. These are more important is you're actually generating a library yourself, if what you're generating here is something that you would then want to share on npm with other people. But we're not generating a library we're actually generating an application, so these fields are not very important. In fact, I'm just going to press Return through all of these fields, and then npm will show us the JSON file that it's going to create, and say, is this okay? And, yes. We're happy with that. It's a very basic, empty configuration, but that'll do for what we need. So we've got npm set up, but we haven't got any packages yet, so that's not very useful. What we want to do is install jQuery. Now, obviously we want to make sure we have the same version of jQuery that we did before, because we don't want to upgrade the application, we don't want to retest it with a new version. So, if we switch back to Visual Studio, we can see that it's currently on jQuery 1.11.3. So, what we can do is, npm install firstname.lastname@example.org. And then importantly, we need to put - - save. Now the - - save is important here, because it tells npm to update our package.json file and actually record the fact that we've got jQuery version 1.11.3 in it. If we don't put the save in it will download jQuery for us, but it won't remember that it did, and that can cause a problem called the invisible dependency problem. So, always put - - save. Okay, so that's finished. If we now have a look in the package.json file, we can see there at the bottom that it's added jquery 1.11.3.
Yarn and Bower
So we've talked a lot about npm, but what other package managers are there? So, Yarn is a relatively recent entrant onto the scene, it was released in late 2016, and it's a replacement for the npm client. So, it still works with the npm registry and the package.json file, so this is important because they haven't gone off and created their own registry, their own repository, and then they're not asking people to start uploading their packages to somewhere new. What they're trying to do is to solve some of the practical problems that people have been having with npm. So that's developers having different package versions, so that's something we touched on briefly earlier when we talked about semantic versioning. With Yarn the version of every package is locked down to that exact version at the time of installation. It allows a flat dependency structure as well. So, for example with npm, if you're using it for the front-end you can have a problem where you can end up with multiple multiple versions of a package. For example, if you have two different things that depend on jQuery you might end up with two different versions of jQuery in your dependency chain, and then that's a problem because obviously in a web browser you can only run one version of jQuery at a time. So yarn allows you to do that. It also removes the invisible dependency behavior, so this is what we saw when we were doing a demo when we were installing a package and we had to put - - save on the end in order to make it actually update the package.json file. So that behavior is gone, Yarn does that by default. It also introduces some caching to improve performance. So as the npm client will always be going to the internet to try and retrieve the packages, Yarn provides a local cache of packages on your machine, so that if you've already installed a package in one website, or one application, if you then need the same package in another one it's already got it, it doesn't have to go and download it again. So, Yarn looks like a very promising effort, it's new, it's not been used that widely so far, but it has been developed by Facebook so it should be well supported, and they're using it now in the production systems at Facebook, so I'd recommend you checking it out because it may be a good alternative to npm. The other widely-used package manager today is Bower. Now, Bower is a front-end package manager, and when Node.js first came out with npm as its package manager is was very much good at server-side applications, so people thought, well, we need a package manager for the front-end as well to use to build our web applications, so they came up with Bower. And the one of the main differences with npm is that it only allows a single version of each package so you don't get this problem that we mentioned earlier where you might have three different versions of jQuery all being referenced at the same time by different dependencies. So, Bower gained popularity around 2012, 2013, and it's still used widely in a lot of projects. But, generally, new projects now are trending towards using npm instead of Bower, and that's because people have realized that you don't really need the special functionality that Bower provides, that actually you can do everything that Bower can do, you can do it with npm, and additional tools that we'll cover in later modules, such as Webpack. So, although Bower is still a very useful tool as a front-end package manager, it's sort of fading out of popularity now in favor of npm. And you can see this here, if we look at the Google trends graph in the last five years, you can see that apart from the Christmas dips the npm's popularity is continuing to increase, whereas you can see that the trend line for Bower is now sort of in a downward direction.
How Transpilers Can Help
Demo: Converting JS to Typescript
CommonJS, AMD, and ES6 Modules
Benefits of Using Modules
Demo: Using AMD Modules
Making Front-end Code Maintainable with Frameworks
What's Wrong with jQuery?
Popular Front-end Frameworks
So that sounds great, but what front-end frameworks are there? Well there's quite a lot. There's Backbone, Knockout, Polymer, React, Angular 1, Angular 2, and many, many more. If you look at todomvc.com, you can see just how many there are. And this is just a small sample. As a side note, todomvc.com is a useful resource for looking at these frameworks. They've implemented the same to do list sample application using several different frameworks so that you can have a look at the code and compare how each framework works. However, in this course we're going to focus on the React and AngularJS because these are the two most popular frameworks at the time of writing this course.
Demo: Using Angular for Data Binding
Angular vs. React
So what have we learned in this module? Well we've learned about how using a UI framework helps you separate your logic and presentation. We've learned how the data binding that these libraries provide allows you to reliably ensure that the page is up to date. And because your code is more maintainable as a result, it leads to faster and less buggy development. Now as always, we've only scratched the surface of this. If you're interested and you want to learn more about Angular or React, here are a few Pluralsight courses you could consider taking a look at.
Automating Build Steps with Task Runners and Bundlers
In this module we're going to wrap up the course by talking about task runners and module bundles. So we're going to start off by reviewing how do we build an app for production. What do we need to do to our web application to prepare it for a production release? And then we're going to talk about task runners and how they fit into that. And in particular, two of the most popular task runners, Grunt and Gulp. Following that we're going to talk about module bundlers. We're going to find out what they are and we're going to talk about two of the most popular ones, Browserify and Webpack.
Building a Web App for Production
Demo: Grunt and Gulp
Npm as a Task Runner
The final thing we're going to talk about in this module is a recent trend to use npm as a task runner. So Grunt and Gulp became popular for building web apps because people needed a way to assemble a pipeline to do things like bundling and minification of their scripts and CSS files and Grunt and Gulp provided a pipeline that was fairly easy to construct that could do that. But recently as module bundlers have started to gain more functionality, people have realized that actually the module bundler provides all the functionality they need out of the box and they don't necessarily need a task runner like Gulp or Grunt anymore. But we still need a way to trigger the module bundler and we may need a way to do some other tasks as well, such as running unit tests. So the need for a task runner has not been avoided completely. People started to realize, well hold on, npm's package.json file has a scripts section and in that scripts section you can define scripts that run operating system commands and run installed packages. You can also run multiple commands using the double ampersand syntax. So people have realized with this, actually why don't we just use npm's task running feature because we don't need the complex pipelines anymore that Grunt and Gulp allow us to construct, we just need a simple way of running the common commands that we're going to need as we build and run our application. Let's take a look at this. Back in the conference planner, we can see the scripts section in the package.json. Here we've defined one command called build, which runs Webpack with a -p argument, which tells it to run a production build, that means to minify the output. There's also an extension for Visual Studio called the NPM Task Runner. If you install this, Visual Studio's Task Runner Explorer window is updated to show scripts from the package.json file as well as from gruntfile and gulpfile. Here you can see this in action. Our custom build task is there and just like with Grunt and Gulp we can right click and we can run it and we can set bindings to before build, after build, clean and project open. So this is a trend where people have realized that npm's functionality here is actually all that's required when we're working with module bundlers. Of course if you have a more complex build process in your application, you may still need something like Grunt or Gulp to set up all the build steps. But in many cases, for simple build scenarios, just using the NPM Task Runner like this is all you need.
Chris has 15 years of commercial software development experience, in recent years having a particular focus on ASP.NET Web Development.
Released13 Jun 2017