What do you want to learn?
Leverged
jhuang@tampa.cgsinc.com
Skip to main content
Pluralsight uses cookies.Learn more about your privacy
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
Description
Transcript
Exercise files
Discussion
Learning Check
Recommended
Course Overview
Course Overview
Hi everyone, my name's Chris Jones, and welcome to my course Beyond ASP.NET MVC: Modern Web Development Demystified. I'm a full site web developer, with 15 years development experience. Web development has changed a lot over the last few years. People aren't just using ASP.NET anymore, they're talking about all sorts of tools like Gulp, Grunt, Webpack, TypeScript, Babel, NodeJS. The list goes on. It can be very confusing and hard to figure out what these things do, and whether you need to learn them. So, in this course, we're going to take you on a journey through recent front-end trends. And along the way you'll learn what these tools are, why they exist, and we'll be doing demos to give you a practical insight on how these tools work. More specifically, we'll be covering Package Managers, Transpilers, JavaScript Modules Front-end Frameworks, Task Runners and Module Bundlers. By the end of the course, you will have a high level of understanding of what these tools are and how they can help you as a web developer. Along the way, we'll be suggesting other courses that you can take to learn about the technologies in more detail. I hope you'll join me on this journey with the Beyond ASP.NET MVC: Modern Web Development Demystified course at Pluralsight.
Overview
Overview
Hello, my name's Chris Jones, and welcome to Beyond ASP.NET MVC: Modern Web Development Demystified. Ah, it used to be so simple, didn't it, creating a web application. All you had to do was create an ASP.NET MVC project, add some controllers, and code them up, add some views, and put your HTML in, and then maybe add some JQuery for some front-end interactivity. But then, over the last few years, people have started talking about Angular, React, Node.js, npm, Bower, AMD, CommonJS, TypeScript, Babel, Yarn, RequireJS, ES6, ES2016, Modules, Webpack, Gulp, Grunt, Browserify, what do they all mean? And which of them do I need to learn? And that's what we're going to be focusing on in this course. So, we're going to take you on a very high-level journey through recent trends in web development, and we're going to talk about all the tools and technologies that are involved. Now, we're not going to go into a lot of detail about each tool, but we're just going tell you enough so that you understand the purpose of the tool, you understand why people are using it, and therefore, you understand why you might want to learn more about it. Along the way we're going to demonstrate adding some of these new features into an existing ASP.NET MVC application. And this is to give you a bit more of a practical, real-world example of how these new tools can help improve your code, whether that's to improve maintainability, or whether that's to get you coding faster. And therefore, as a result, at the end of this course, you'll be able to choose which of these tools and technologies you want to invest your time in learning. We'll recommend some other Pluralsight courses that go into more detail in each of the tools, so this course really is to give you a high-level overview so that you can make your own decisions about which tools to invest your time in learning. So, who should take this course, and what are we going to cover, more specifically? Well, this course is aimed at developers who are familiar with ASP.NET MVC and have a basic working knowledge of JavaScript and CSS. Now, you don't have to know ASP.NET MVC, a lot of high-level concepts you'll understand perfectly fine without it, but we're going to be drawing quite a few comparisons with ASP.NET MVC, and showing how things are different from it. So, it helps if you have some knowledge of that. The first thing we're going to talk about is package managers. And, we'll introduce you to those, we'll tell you what they are, and we'll cover some specific ones, such as npm, Bower, and Yarn. Then we're going to move onto JavaScript transpilers. And again, we'll introduce you to the topic, tell you what they're all about, and we'll talk specifically about a couple of the most popular ones, that'll be TypeScript and Babel. We'll then move onto JavaScript modules, again we'll give you an introduction, we'll tell you what they're for, and we'll talk about the different types of JavaScript modules. Then we'll move onto front-end frameworks, describe what they're for, describe why people are using them, and talk a little bit about Angular and React. And finally, we'll move onto task runners and module bundlers. Again, we'll start by providing an introduction to them and then we'll talk specifically about Gulp, Grunt, Browserify, and Webpack. Welcome to the course.
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
Module Overview
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?
So, what is Node.js? Well, it's often referred to as a server-side JavaScript runtime, because it was originally designed to allow people to write server-side applications in JavaScript. So, why learn .NET, why learn C#, why learn Java, why not just write your server side in JavaScript? That's the idea. That has also become popular outside of this, it's very popular now for build tools, as we're going to see in a minute. So don't get too hung up on the word server-side, what it's really saying is, Node.js allows you to run JavaScript outside of the web browser, run JavaScript within your server environment, no web browser involved. So what that means is there's no window object, there's not document object. Instead, there's a new set of API modules that Node.js provides. So it provides functions to, for example, read and write files from the disk, or something obviously you couldn't do within a web browser context because you didn't have permission to client's disk, but, because you're running Node.js code on your server-side environment, you do have permission, just like any other server application would. So Node provides a big set of APIs that you can use to do things like that. It also comes with its own package manger called npm, that's the node package manager, imaginatively titled. And this is the package manager for Node and IT to download all of the libraries and modules that run on top of Node.js. Now, you might be thinking, that's all well and good, but why should I care about Node.js? Well, in the front-end ecosystem today almost all the build tools for web applications run on top of Node, even Microsoft has decided not to support script bundling and minification in ASP.NET Core, and are recommending they use a tool like Gulp or Webpack instead, both of which run on Node.js. So, it has now become essential for any web developer to have node installed on their machine and understand the basics of how it works.
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 jquery@1.11.3. 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.
Module Summary
So, what have we learned in this module? Well, we've learned about how package managers can save you a lot of time when you're working with third-party libraries. We've seen about how they've managed dependencies and version for you, so that you don't have to do all that stuff manually. We've learned what Node.js is, we've learned about how it's the server-side JavaScript runtime, and we've learned about npm, its package manager. And we've also learned about Yarn and Bower, we've learned how Yarn's a promising new kid on the block to replace npm, and we've also learned about Bower, and how it's been very widely used as a front-end package manager, but perhaps it's losing ground in brand new applications that are being made today. We've barely scratched the surface of these package managers in this module. So, if you want to know more, I'd recommend taking one of these Pluralsight courses. These courses go into a lot more detail about these package managers and you can learn a lot more about what they can do for you, and how they can help save you time.
Modernising Your Javascript with Transpilers
Module Overview
In this module we're going to talk about JavaScript transpilers. Now, if you don't know what a transpiler is that's absolutely fine, because by the end of this module you will do. And you'll also know, why we would use a transpiler, you'll know what it does, and you'll know about a few of the most popular transpilers in use today, and that's TypeScript, Babel, and CoffeeScript.
Javascript, Past and Present
To understand why we might want a transpiler, it's best to start by looking back at a history of the JavaScript language. So, JavaScript was first unleashed in the world back in 1996 as part of Internet Explorer 3 and Netscape Navigator 2. Now, that's long time ago, that's more than 20 years since JavaScript was first released. And initially it was just a very simple scripting language, designed to be able to add a little bit of interactively to web pages at the time. And as the web evolved so did JavaScript. So, in 1999 a standard called ECMAScript 3 was released. ECMAScript was a compromised name because the original JavaScript name was owned by Netscape, and Microsoft therefore used the name JScript when they implemented in Internet Explorer to avoid any trademark issues. So the standards body eventually agreed on ECMAScript as the official name for the language. So the ES3 standard was the first real update to the specification. It added support for features like Regex, try/catch, and more, and these were first fully implemented by Internet Explorer 6 and Netscape Navigator 6. And then, nothing happened for a long time, in terms of adding to this language specification. The 2000s were almost a lost decade for the JavaScript language, and during the 2000s then browser vendors started going off in their directions, the lack of standardization meant that browsers started implementing their own extensions, their own features because there was no standard to follow. Until, finally, in 2009, the ECMAScript 5 standard was released. So this added support for things like JSON, Array manipulation, Strict Mode, and loads of other goodies. And this was then finally implemented by Internet Explorer 9, Chrome, and Firefox, and Safari. Netscape Navigator had obviously disappeared off the scene in the meantime. But, the problem for web developers was this, it's fantastic that we've now got an ECMAScript way of supporting JSON, except that the standard was released in 2009, Internet Explorer 9 didn't come out until 2 years with that support, and even when it did come out, a lot of people, a lot of businesses are still using Internet Explorer 8, or 7, or even 6, so there are all these great features now in the latest ECMAScript release, but as a web developer, I can't use any of them because most of the people using my website, they're not using the latest version of browsers, they don't have these latest browser versions that support the standard. So, the standard is great in theory, except that nobody can actually use it because we need to support all of these older browsers that are still around. Now, looking forward, and this problem is just going to continue, because ECMAScript 6 was released in 2015, and that's now supported by the latest versions of all the major browsers, but it's not supported by IE11, for example, which some people are still using, it's not supported by older versions of mobile operating systems, and mobile is really the big problem nowadays. It used to be Internet Explorer that was always a problem, where people were using ancient versions of the browser and never updating, that's largely improved nowadays, but mobile has taken over as a problem instead, especially with Android handsets, which never get updated because the phone manufacturer doesn't want you to have an updated operating system, they want you to buy a new phone, and so they don't supply you with an update. So there's a lot of mobile devices in particular, but desktop PCs as well, running all the versions of the operating system or the browser, which don't support these latest standards. The other thing to notice is that the ECMAScript body have now decided to move to annual releases of the standard. So, there's an ECMAScript 2016 now, which adds a couple of new features to the language. And there's going to an ECMAScript 2017 as well, which has a couple more features. And going forward this is going to continue, they want to have small incremental annual releases rather than waiting years in between each release. So that means there's a lot of different versions of ECMAScript going on, and there's a lot of different browsers, and trying to track which browser supports what, and trying to figure out, can I actually use this JavaScript feature, having to cross reference it with some chart that's got all the different browsers on it, and trying to figure out what you're usually using, and therefore, is this feature usable? As a web developer, I'm sure you've come across this problem, and it is a nightmare for the industry.
How Transpilers Can Help
So, how do we solve this problem of not being able to use the latest JavaScript features because some of our users have a browser that doesn't support them? Well, enter a transpiler. So, what does a transpiler actually do? Well, it takes some input files, which are written in one language, runs them through the transpiler, and produces JavaScript files as an output. And really, at its heart this is all that a transpiler is doing. So it's taking in input files, which depending on the transpiler might be TypeScript files, they might be CoffeeScript files, they might be something else entirely, it takes those files in and transpiles them into JavaScript. And, we call it a transpiler because generally a compiler takes a file written in one language and compiles it down to an output in a lower-level language, whereas, with a transpiler we're not really compiling down to a lower-level language, we're just translating it sideways really, into a language of a similar level. So, now we know what a transpiler is, but how can that help us solve our problem? Well, let's have a look at a few of the common transpilers that are in use today and we'll see what they can do for us. So the first one we're going talk about is Babel. What this does, is allows you to write your JavaScript files using the latest version of the ECMAScript syntax. And then when you write through Babel it will transpile it down into JavaScript that will run on a system that supports ECMAScript 5. And you can select the output format, but ECMAScript 5 is the default, and that allows you to run it on the all recent web browsers. Bear in mind that ECMAScript 5 was released back in 2009, so pretty much all browsers that are in use today do support that. Babel has a plugin architecture. So, as well allowing you to transpile one version of ECMAScript to another, it also has plugins that can process other language features such as JSX, which we'll touch on later on, but which is a way you can embed HTML directly in your JavaScript files. Another very popular transpiler today is TypeScript. Now, TypeScript does a very similar thing to Babel, insofar as that it transpiles the latest ECMAScript syntax back into ECMAScript 3, or ECMAScript 5. But on top of that it adds a typing syntax, which allows you to define variable types in your TypeScript code. That is an extension on top of JavaScript, effectively TypeScript is a superset of JavaScript, where it adds these typing support, and that can be very good for avoiding bugs in your code, because obviously JavaScript as a language is weakly typed, it doesn't support specifying types for variables. So there we have Babel and TypeScript. Both do very similar things, but then extend the language in different ways. CoffeeScript is the final transpiler that we're going to talk about. Now it's very different to Babel and TypeScript because it actually has a completely different language syntax. So this is not something that allows you to transpile the latest version of JavaScript backwards, no, it's a completely separate language, but it outputs as ECMAScript, so it allows you to write your JavaScript applications in CoffeeScript instead, but then produce JavaScript so that they can be run within the web browser. Now, CoffeeScript was the first of these three transpilers to be released. And it's kind of fallen out of favor recently, partly because it has its own completely separate language syntax, so it's harder to get developers to work on it, it's harder to find developers who know the language, and also because, in a lot of ways, Babel and TypeScript now provide the facility to write better client-side code without needing a completely separate language. So, CoffeeScript is now, it's probably safe to say on the decline, as you can see on this Google trends graph here. You can see that TypeScript had a real spike when it was first announced, that was in 2012, and then it really gained popularity in the last couple of years since it was announced by the Angular 2 team that they were going to write Angular in TypeScript, and it's become the recommended language for Angular. So, TypeScript is very popular now, Babel is also very popular particularly in the React community, and we'll talk more about React and Angular in a later module. CoffeeScript is still an option, but it's definitely not as popular as the other two, and it does involve you having to learn a completely separate language. But if you're a web developer who's interested in using one of these transpilers, TypeScript or Babel would definitely be a good place to start.
Demo: Converting JS to Typescript
Okay, so we're going to demonstrate how to use a TypeScript file in Visual Studio, and we're going to do that by taking one of our existing JavaScript files and converting it to TypeScript. Okay, so I'm here in Visual Studio, and I've got open the ConferencePlanner sample application that we saw earlier on. So, what I've done here is opened up this ajax.js file. This is just a JavaScript file that's part of the project that somebody wrote at some point as a help of making Ajax calls. So, let's convert this file to TypeScript. Now, given that TypeScript is a superset of JavaScript that should be very easy. So let's start by literally just renaming the file to ajax.ts. Oaky, so we've now got this as a TypeScript file. If we open the Error List, we can see that we've got one error, Cannot find name $. So, one of the restrictions that TypeScript enforces is that all global variables must be declared. In this case we've got a $ variable, which is not declared, therefore TypeScript doesn't know what the type of it is, so it doesn't know how to validate it. So there were two main ways we can solve this problem. The simplest one is we can simply tell TypeScript the $ is a global variable that is available and it might have any type. That's the simplest way to solve the error. And we do that by simply going to the start of the file and typing in declare var $: any. So that's telling TypeScript that there is a variable called $, and that it could have any type. And that will turn off TypeScript's type checking, but it will allow the code to compile it, it will allow the code to run. However, obviously we don't want to have to do this in every single JavaScript file that uses jQuery. And it would be nice if we had some better IntelliSense so we knew what methods were available in jQuery that we can call. Well, the solution to that is to add what's called a DefinitelyTyped package to the solution. Now, this is a NuGet package, which provides type definitions for common libraries like jQuery. And the DefinitelyTyped project is pretty massive, and it has a lot of type definitions for a lot commonly-used libraries. So, let's do that. So we'll start by removing this code that we've just added. So we should get the error back now, if we have a look in the Error List, yep, our error has returned. So, let's solve it using a NuGet package instead. So if we go into our NuGet Package Manager, if we search for jquery typescript. And then if we scroll down a bit here, you can see that there is this package called jquery.TypeScript.DefinitelyTyped. Now this is definitely the one that we want, this is the one for jQuery. The slight difficulty here is knowing which version to install, because the versions of the typing package doesn't necessarily match the version of jQuery itself. So ideally, we know that we're using jQuery 1.11.3, we found that out in the last module. It would be nice if we could here select jQuery 1.11.3 in this drop-down list. Unfortunately it's not that easy. So for now we'll just install the latest version of the DefinitelyTyped definitions, but we need to be aware that that's going to give us potentially extra methods that don't exist in the version of jQuery that we are actually using. Okay, so that's finished. And if we go back to our TypeScript file, call up the Error List, we've got no errors, the error has gone away. And also, what we'll find is, if we type the period after the $ again, we're now getting an autocomplete list, which shows us all of the methods available in jQuery. So here, just by adding the DefinitelyTyped package, we've removed our error and we've also improved our development experience because now we've got very good IntelliSense for the jQuery library. So what did it actually do when we just installed that NuGet package? Well, if we have a look down at the Solution Explorer we can see a folder called typings. Now, this folder has been created by the NuGet package and it contains a file called jquery.d.ts. If we open this file, we can see that this is simply a TypeScript file that contains the definitions for all of the jQuery elements, all of the jQuery methods, all of the jQuery classes. And this is used by TypeScript to provide the IntelliSense and also to provide type validation. So that's great, but we were talking earlier about the fact that TypeScript allows you to use new ECMAScript features and complies them down into older versions of JavaScript. So how does that work? Well, if we set our Solution Explorer to Show All Files, we'll see her that we actually do have an ajax.js file that's been generated for us. And if you look at this file, it's pretty much identical to our ajax.ts, but with some minor changes to the whitespace. So this is what the TypeScript compiler has created for us. It hasn't needed to change any code because we haven't used any modern ECMAScript features, so it's effectively just output a copy of the input file unchanged. But what about if we change our TypeScript file to use a more modern JavaScript features, such as an ECMAScript class? So here, I've rewritten the ajax.ts file to use an ECMAScript class. Let's see what's been generated in the ajax.js by TypeScript. As you can see, now, the two files are quite different. TypeScript has generated me a JavaScript file that will supported by all the browsers, but I've been able to write my code in the latest ECMAScript style. You'll also notice a map file's been generated. This map file allows you to debug your original code while it's running in the browser. So even though the browser's actually running the generated JavaScript code, when you step through in the debugger you see your original TypeScript code, let's take a look at that. Here's the Conference Planner running in Chrome. You can see that in the Chrome debugger it lists both the ajax.ts file and also the ajax.js file. If I now click on the link to activate the code, you can see that the breakpoint gets hit within the ajax.ts file, even though what the browser's actually running is the underlying JavaScript. This relies on the source map file that the TypeScript compiler produced. Similarly, Babel and other transpilers also support generating these source map files.
Module Summary
So, what have we learned in this module? Well, we've learned that browsers take time to adopt new JavaScript language features, and we've learned that transpilers help to bridge that gap by converting JavaScript code that was written using the latest JavaScript language features into older JavaScript code that can be understood by the web browsers that are on the market today. In summary, transpilers allow us to use the latest JavaScript features today and add some of our own extensions into the language as well. Now of course, we've barely scratched the surface of transpilers in this module. If you're interested and you want to learn more, I'd recommend taking a look at one of these Pluralsight courses. These courses will take you on a deeper dive into the transpilers that we've talked about today, if you want to get a better understanding of how they work.
Cleaner, More Structured Code with Javascript Modules
Module Overview
In this module we're going to talk about JavaScript modules. Now, if you've ever worked with a large JavaScript application and found that the code is becoming a nightmare to maintain then you probably need JavaScript modules. So, during this module we're going to learn why we should care about modules, and we're going to learn about the three main types of modules, so that's CommonJS, AMD, and ES6.
Why Do We Need JavaScript Modules?
So, to understand why we might want to use a JavaScript module, let's start off by having a look at some JavaScript code that doesn't use modules. So the code that we can see here is classic JavaScript code written without using any module system. In this code we've defined a JavaScript function called calc, within that function we call another JavaScript function called ajax, which has a setErrorPrefix method on it. So, what are the problems with this code? Well, for starters, calc is a global variable, so as soon as the application starts to get to any sort of size, you might end up with two calcs. And if you have two calcs in JavaScript you won't get any compiler errors, you will just get a situation where one calc variable overrides the other one, leading to problems that can be pretty hard to debug. Another problem that we've got here is that we're making a direct reference to another global variable. So what does that mean? Well, it means that all of our JavaScript code files become very tightly coupled to each other and these global variables end up hard coded all over the place in our code, and that can create some maintainability problems. The other problem with this code is that having hard-coded dependencies like this means that the load order of the JavaScript files matters. So you need to remember which files we include first and which one to include second to avoid getting JavaScript errors in the browser when you load up the application. For example, if we go back to Visual Studio and have a look at the ConferencePlanner application, we can see here that the ScriptBundle has had to be created with the files in a specific order to avoid compile errors. Now, obviously here, in this application it's not a big deal, but if you've got a larger application that's got tens or hundreds of JavaScript files, just working out what order you need to include them in is a problem in itself, let alone actually maintaining that list of JavaScript files in the correct order. So, how do we solve this problem? Yep, you've guessed it, JavaScript modules.
CommonJS, AMD, and ES6 Modules
So, let's take a look at the three main modules systems in use today. The first is CommonJS modules. So CommonJS is a standard for server-side JavaScript applications, which was first released in 2009. CommonJS is just a standard for how this should work, it's not actually an implementation itself, but it is implemented by Node.js. And the way modules work in CommonJS is that there is a global method called require, and you call require passing it in the name of the module that you want. The require method will then go off and find that module, load it up, and return a reference to it. If the module's already loaded, it won't need to load it again, it can just return you the reference that it's already got. To create a module you code it in a JavaScript file and there's an exports variable, which you can add methods to, if you want to expose them to callers of your module. Now, this works fine in a server-side environment such as Node.js. But the problem with using this in a browser is that the require method synchronously loads dependencies. So if you were to use this in a browser the require method would then block the system while it went off, found and downloaded the Ajax JavaScript file, and loaded it up, which isn't really what you want in a browser environment because it will make the browser unresponsive while it's loading these dependencies. But let's take a moment to look at what CommonJS does give us. It's illuminated our global variable problem, because we reference the other module using the require method rather than using a global variable. And it's illuminated our file load order problem because we simply reference the other module that we want, and the module loader will go and find it for us, so we don't need to worry about what order we include the files in. So, in conclusion, CommonJS is great and it solves our problem, but it doesn't really work that well in a web browser environment. So, some clever people went off and thought, why can't we define our modules asynchronously? So, they came up with a standard called asynchronous module definition, often called AMD. So this is a different standard for defining modules that allows it to work in asynchronous fashion. Here, we have a single define function, which wraps all of our code. Into the define function we pass the names of any modules that we depend on, in this case we're passing in ajax, and we also pass in a function that will be executed when all of the dependencies are loaded. And into that function the module loader will pass the reference to the actual modules that we've requested. So the way this works, the code inside of the function will be delayed and won't be executed until all of the modules have been loaded. One of the benefits of this approach is that it allows the module loader to load modules in parallel. So if we passed in five different modules that we wanted, the module loader could go in, download all five of them in parallel and then pass them all in to our function when they've all loaded. Now this pattern is implemented by RequireJS and AngularJS also does something very similar, although it doesn't use the define function, it has its own functions instead. Now, the popularity of these modules systems didn't escape the notice of the people responsible for the JavaScript language, and they thought to themselves, well wouldn't it be great if the JavaScript language actually provided a module functionality, then you wouldn't need to include a live RequireJS, and the browser would know then about the modules as well, so the browser might be able to load them in a more efficient or more optimized way. And so, as part of the ECMAScript 6 release of JavaScript language, they introduced ES6 modules. ES6 modules introduced two new keywords into the JavaScript language. Import, is a new keyword, which allows you to import from another module, and allows you to specify whether you want to import everything or just specific functions. Export is a new keyword, which allows you to export a function from the current file and allow it to be imported into other JavaScript files. Now, at the time of recording, in 2017, ES6 modules are not well supported by web browsers; however, they are supported by transpilers such as TypeScript and Babel, which allow you to start using this syntax now and transpile it into a format that will work with existing browsers.
Benefits of Using Modules
So let's review the benefits of using JavaScript modules. Well, as we've discussed, it allows us to avoid using global variables and the tight coupling that comes along with them. It also allows something called dependency walking. Because in each of our JavaScript files we've defined all the dependencies of that file, it allows tools to automatically walk through all of our JavaScript code and find which files are used and which files are not used. This can provide big size benefits when we're bundling the application, for example, there are tools that we'll cover later on in the course, which will start from your first JavaScript file and walk through the dependency tree of all of the modules that are defined as dependencies of each other, and just bundling all of that code and allow you to identify JavaScript files that you're actually no longer using. Similarly, there are other static analysis tools that can also use this information to walk through your code and find unused code, so, unused methods, some unused files. Because of all that, using JavaScript modules puts us in a position where we have more maintainable and more reusable code.
Demo: Using AMD Modules
So let's have a look at how we might implement JavaScript modules into an application, and we're going to do this by returning to our ConferencePlanner application from module 2. Now we're coming back to the application in the state that we left it at the end of module 2 to make it as clear as possible how the modules work. You can of course make this work with TypeScript, but that's an extra layer of complexity, so for now we're going to go back to the application without any TypeScript files in it. So the first thing we need to do in order to use JavaScript modules is to add a module loading library to our application. So we're going to go with asynchronous module definition, because that's most appropriate in the web browser, and we're going to use RequireJS, which is one of the most popular libraries on the market today. So I've got a command prompt open, and I'm going to install RequireJS. Okay, great, so RequireJS is installed. If we take a look in the node_modules folder, so we Show All Files, in Visual Studio, and then have a look in node_modules, we can see that we've now got a requirejs folder, and a file called require.js, which contains the library code. So, we'll close that file, we know that it's there, but what we do need to do now is include it in our project. So, there are various ways we could do this, but to keep it simple, let's just include it in our template. So, let's open our layout page, and similar to how we've included jQuery, let's include RequireJS as well. Next, let's open our two JavaScript files and convert them to RequireJS AMD modules. So, starting with our ajax.js, okay, so we've changed it to an AMD module. Here you can see the name of the module, you can see its dependencies, so in this case, this module doesn't have any dependencies, and you can see the actual module function itself. The changes are very minimal compared to what we had before, but everything is now wrapped within a define function. Let's do the same to our index. And here we've converted our index page in the same way. Here you can see that we do have a dependency, and that it's then passed in to us as the last parameter. Next, we need to go to the entry point of the application and reference these modules. In this application, which is a single-page application, the entry point is actually in our index file. It's not ideal having JavaScript in a view like this, but for the purposes of this demonstration you can see here that currently the index page is called as a global variable within the onclick handler. We need to change that so that there's a proper JavaScript entry point into the application. So you can see that I've removed the onclick handler with the global variable reference and instead put the MVC parameters in data attributes. If we scroll up, you can see a new chunk of JavaScript. This uses a require function, which is part of RequireJS, and tells it that the code inside should be executed when the page starts up, but only when its dependencies have been loaded. In this case we've specified the index page as a dependency. And we've also simulated the onclick handler using jQuery. So this now still calls the flagAttendance method on the index page, but within the context of a RequireJS require statement. Okay, so that's great, but we've still got a chunk of JavaScript code inline within our HTML page, and this is generally considered to be very bad practice. So, to finish this off, let's move this chunk of code into a separate file. Say to the Scripts folder I'm going to add a new JavaScript file, and let's call it startup. And now, I'm just going to cut and paste the script that we had into this file. Great, done. Now we need to make sure that this file is loaded by the web browser. To do that, we're going to open our Global.asax, and go to our bundle definition. Now here, notice that currently that Ajax.js has to be loaded first before the index.js. That was because we weren't using JavaScript modules and they were direct global referable references. But now, it doesn't matter anymore, so we can actually just change this. (Working) Let's run it and see what happens. Great, here it is, and we can still click the link, the link still works. So, there we go. We've successfully converted the Conference Planner to use JavaScript modules, and now from this point onwards if we want to add new modules, it's just as simple as adding a JavaScript file to that folder and coding the module.
Module Summary
So, what have we learned? Well, in this module of the course we've learned, what are JavaScript modules, and we've learned about the popular module systems that are in use today, and we've seen some of the benefits of using modules, so now you understand why JavaScript module systems have become so popular, and you've seen how you can use them in your application to improve your code's maintainability and make your development experience faster. Of course, as usual, we've barely scratched the surface of JavaScript modules, here are some Pluralsight courses that you might want to take that dive into more detail and give you a better and fuller understanding of these module systems.
Making Front-end Code Maintainable with Frameworks
Module Overview
In this module we're going to talk about front-end frameworks. Now the word framework can be a bit contentious, there are many online debates about what constitutes a framework and what constitutes a library. But for this module we're talking about JavaScript frameworks and libraries that help you render your web app in the browser. So in this module we're going to talk about what's wrong with jQuery? Why can't we just write an application using jQuery? Why do we need anything more than that? We're going to find out what front-end frameworks have to offer us and why they can help us. And we're going to find out about two of the most popular frameworks in use today, so that's Angular and React.
What's Wrong with jQuery?
So why do we even need a framework anyway? What's wrong with just using jQuery for our application? Well there are a couple of pretty big problems, such as with jQuery you've got DOM manipulation directly in the code and you've got hard coded CSS classes and Element IDs. So let's take a look at the conference planner application to see what we mean. Here we're using a hard coded CSS class to select an element, and then we're using the jQuery text method to directly change the DOM. This leads to two problems. First the use of hard coded CSS classes and Element IDs makes our code very brittle. If somebody goes and changes one of the CSS classes because they want to change some style, suddenly some of our code stops working, we can't update the Element anymore, which can obviously lead to bugs that maybe we don't notice immediately and then maybe you ship that bug to a customer by mistake. The other problem is that debugging DOM changes can be very difficult because CSS selectors are page-wide. Because any JavaScript code anywhere in the application could be updating any element in the DOM anywhere, it can be very difficult to figure out why something on the page is changing. For example, you've got an element somewhere on the page and the text in it is changing and you can't work out why, now why is this changing? In order to figure that out you'd have to look through all of the JavaScript code of your entire application to find the faulty jQuery statement. That's obviously a lot of work and at least a code that's not very maintainable. Of course, with jQuery you can specify a scope to the selectors, but it's very easy to make a mistake with that. And tracking down where the mistake is is equally difficult. So how is this different when we use a front-end data-binding framework? Well the framework updates the DOM for you, so we don't have any JavaScript code telling the browser to update a specific element in the DOM, that's all handled for us by the framework. There are no references to CSS classes or Element IDs in a JavaScript code. Again, the framework handles all that for us. Each part of the DOM is generally handled by a particular component in these frameworks and that means that each component owns a part of the DOM. That way you know that one specific component is the only component that is allowed to modify that part of the DOM and that makes it a lot easier to reason about the code and track down issues.
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
So to demonstrate some of the advantages that we talked about when we use a framework, we're going to demonstrate converting our conference planner application to use AngularJS. For this demo we're going to use Angular 1. Now we're going to do this because it's one of the simplest frameworks to integrate into our existing application. If you have a legacy application that you want to start modernizing, Angular 1 is a nice simple way to get started. But if you're working on a new project from scratch, take a look at the latest Angular version, or React, which we'll cover in the next clip. But regardless of which one we choose, the takeaway from this demo will be to understand the benefits of using one of the data binding frameworks. So the first thing we need to do is add the Angular framework to our application. And we're going to do that by using npm, as usual. Great, that's done. Let's have a look in the Solution Explorer. We'll take Show All Files as we've done previously, have a look in our node.modules folder and yes, there we are, we've got angular.js. And you can see the framework code is inside. Okay, so now let's go to our layout page and add a reference to the new Angular library so that the browser downloads it. Great, done. Okay, and now to activate the Angular framework there are a couple of things we need to do. Now you can find out more about these if you take an AngularJS course on Pluralsight. So the first thing we're going to do is register an application module and then we're going to open our startup.js and bootstrap the application. Okay so that's the plumbing out of the way, now let's have a look at the interesting bit. If we go and open our index.cshtml and scroll down a bit, we can see here that all of the information about the conference is currently being output using the MVC Razor syntax. So effectively the data binding is happening within the server side within the MVC view. So the first step is for us to change this so that instead of using MVC view data binding, we use Angular data binding. So let's replace these data binding expressions with Angular ones. Okay so these expressions are all bound to something called item. What is item? Well we need to define that as well. To do that we'll add an ng-controller directive to this div. This specifies which Angular controller will be responsible for this part of the DOM. So I've named one ConferenceListItemController, so now we need to go and create it. Okay, so let's scroll up to the Scripts folder and let's create a new JavaScript file. And we'll call it conferenceListItem.controller.js, because that's a convention that's generally used with AngularJS projects. Okay so we've got our new file, what are we going to put in it? Well we need to create here an AngularJS controller. Okay so I've pasted in a skeleton for a controller. This controller specifies which module it's part of, this is the app module we defined at the start. And it defines this controller and the code within it. Now currently I've just got all these properties set to null, so that means they'll all come out blank if we run the application. But the important point is that the properties that we're seeing here are now automatically data bound to the DOM using the data binding expressions that we can see in the index page. Right, so let's fix this up so that the values are displayed correctly on the page. Now to do this I'm going to use a bit of a hack. I probably wouldn't recommend designing an application this way, but it allows us to quickly illustrate the point. I'm going to add an HTML attribute called data-conference and into that I'm going to pass a JSON serialization of our .NET conference object. If we now go to our JavaScript controller, we can put some changes in that will allow us to pick this up. Done. Here we're using the $attrs parameter, which Angular provides, to access the Element attributes and read the conference attribute that we just put there. We then deserialize it into an object and read its properties. Okay so now it's time for the moment of truth, does all this stuff that we've been doing actually work? Well let's find out. And yes, almost. So there's a problem with the dates that we can see there, but apart from that, the list of conferences is still there and the conference name, location and description are all displayed correctly. So that's a success. We've got Angular into our application and we're using it to data bind some of the values on the page. But wait, you're thinking, we haven't actually solved the problems we set out to resolve around hard coded CSS classes and direct references to the DOM with jQuery. No, you're quite right, we haven't done that. So let's look at that now. Returning to Visual Studio, let's have a look at our controller. Here we're setting up data bindings for values to display on the page. But in the controller we can also add functions. Let's add one like this. Here we've added a function called flagAttendance that will call our existing indexPage.flagAttendance method, passing in a URL from the attributes and passing in the ID that we got from the server. What about that URL, where's that coming from? Good point, let's go and add it. So let's add the URL as another attribute to this div. Good, and now let's change our link so that instead of putting the URL on it as an attribute, it's bound to our new method that we added in the controller. Great, that's all hooked up. So hopefully when we click on the link we should find that the control flow comes into our controller and calls the method. And now that we've done this, if we open our startup.js, we can actually remove this block of jQuery code because the click handling is now handled by our Angular bound function, gone. Looking back in our controller though, there's one thing here that won't quite work. We're calling indexPage as if it's a global variable, but in a previous module we changed it so that indexPage was now an AMD module. As we're using Angular, we can convert our code form AMD modules to use Angular constructs such as services, factories and directives. In this case our index page should be converted into a service. So let's do that. Here's our existing code for the indexPage, now let's replace it with a service. Okay, so here we've replaced our indexPage AMD module with an indexPage Angular service. We've also removed our reference to our custom Ajax helper, as instead we're now using Angular's $http built in HTTP handler. Now let's go back to our controller. Here we need to add a reference to our new indexPage service and we need to update our flagAttendance method to take the return value and put it into the attendeeCount variable. Finally, let's return to our startup.js and let's remove our use of require js now that we no longer need it. Done. And the final thing we can now do is get rid of our ajax.js. Gone. Alright let's run it and see if it works. Yep, looks good. Let's try clicking the link. Yep, yeah the link works. The number gets incremented so everything is working. Well, except the date that is. Let's fix that up quickly. The reason for the problems with the date is because the JSON standard doesn't specify a format for dates. So what we'll do to get around it in this case is we'll just do the date formatting on the server side. So let's open up our Conference file and in here let's add a string property that provides the formatted date as a string. And then let's switch back to our controller and let's read the string instead of the serialized date time. There it is. Back in Visual Studio, let's just recap the benefits of what we've achieved by putting angular into our application. So previously we had two places where we had some pretty horrible jQuery code with hard coded CSS selectors and direct DOM manipulation. Here we've replaced those things by just a variable assignment here in the controller. And in the index page we've just got a function call to handle the click instead of a bunch of jQuery. Look at the code now compared to how it was at the start of this demo and I think you'll agree that this code is a lot more maintainable. It's obvious what happens when someone clicks on the link, you can see the ngclick function name specified there. And you can easily trace it through to the controller. Equally when we get some data back from the server, we can update the page just by a variable assignment, a simple variable assignment, and the data binding here in the HTML will take care of updating the DOM for us. So we've got some immensely powerful benefits for making this transition to a data binding framework such as Angular.
Angular vs. React
Okay so we've seen the demo of some of the benefits of using one of these data binding frameworks, but how do you decide which one you should use? With Angular and React being the frontrunners, how do you know which one of these you should invest your time in? Well let's have a look at what they have in common and what works differently. So Angular provides a way for you to create data-bound components, as does React. That's what they have in common, that's what they both offer you, a way to create components which deal with part of the HTML page and which provide data binding for you. Now Angular provides two-way data binding, that means that if you bind a variable in your controller to an input box, for example, if you change the variable, then the contents of the input box will change and it also means that if the user types into the input box, your variable will change. So that's two-way data binding. React, on the other hand, prefers one-way data binding whereby any input from the user needs to be explicitly manually handled in your template. Neither of these approaches is necessarily better or worse than the other, it's a difference in design philosophy. In Angular, templates are specified as HTML files or as strings within the controller. In React you can do this as well, but the standard is to use something called JSX. This is a file format where you have a JavaScript file, but you embed HTML within the file. A bit like the way the Razor syntax allows you to embed C# within an HTML page. Angular is a framework that includes support for forms, routing, HTTP calls, and more. It's a whole framework that you can use to build your application. React, on the other hand, is a library for building user interfaces. So it provides facilities for you to create components and to do data binding, but that's where it ends. React doesn't try to provide you with the ability to make HTTP calls or do routing or anything like that. It's purely for the UI data binding. With Angular TypeScript is the preferred language. Indeed Angular 2 and later versions are written in TypeScript. With React, Babel is the de-factor transpiler. Now again, TypeScript and Babel are different but similar transpilers as we saw in a previous module. Neither of them is necessarily better than the other, but the communities of Angular and React have sort of aligned around these particular tools. Angular is opinionated, it's very opinionated, it gives you a structure for how you should build an application and it expects you to follow it. The good thing with this is that it provides consistency between Angular applications. If you work at one company and you work on an Angular application and then you go and work at another company and they use Angular as well, you can very quickly dive in and understand how the code is structured. React, on the other hand, leaves a lot of it up to you. So an application that's using Angular is probably just using Angular and maybe a couple of other libraries because Angular provides so much functionality outside the box. With React, it's providing you with the data binding but on top of that you then need to include a lot of other JavaScript libraries to handle things like Ajax calls, routing, et cetera. So that means two things, one it gives you more flexibility to pick and choose the libraries that you like, but on the other hand, it means that React's applications are all different. People can choose different libraries that do a very similar thing. And it can mean it takes longer to pick up in your application because you have to learn all the libraries that it's using and what they do. So how do you choose whether to use Angular or React? Well, they're both great options, they are both great frameworks, they're both very widely used. Angular is a product of Google, React is a product of Facebook, both massive companies, both very well supported. Angular provides a full framework and makes decisions for you, as we were just saying, whereas React is a UI library and you decide the rest. So for example, if you're a full stack developer and you don't have that much time for the front-end, you might want to pick Angular because you just put it in and mostly it'll just work, and you just follow the patterns laid out by the Angular framework. On the other hand, if you're more focused on the web side of things and you want to be able to find different libraries to do things in better ways, then maybe React is a good choice for you. But as we said, both are well supported and both have very active communities to help you out if you get stuck.
Module Summary
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
Module Overview
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
So let's start off by reviewing what it is we need to do when we build a production release of our web application. Typically we'll need to transpile TypeScript or JSX or some other similar language into JavaScript files that the browser can use. Similarly we need to transpile LESS or SASS or another similar language into CSS files that the browser can use. Then we need to concatenate all the JavaScript files together and we need to concatenate all the CSS files together into a single file to improve performance in the browser. And then after that, finally, we need to minify those files to reduce the size of the JavaScript and CSS payload that the browser needs to download. So that's great, you might be thinking, but doesn't .NET already do this? Well yes, we already have System.Web.Optimization. Now this works by defining your bundles in the C# code. Indeed, if we look at our conference planner application, we can see here that we've got two script bundles registered. One with the JavaScript files and one with the CSS, and here we've got a custom LessTransform that's transforming our LESS file into CSS along the way. Because of the way the bundles are defined, the bundling process happens at runtime, when the app starts up. As well as being a bit inefficient as the bundling happens every time the app restarts, this means that if something goes wrong you don't necessarily know about it. For example, the .NET JavaScript minify frequently fails and just returns the unminified code to the browser. And unless you manually check the file being emitted, there's no way to know that this has happened. Now the built in script bundle functionality is extensible, it allows you to use customer transforms and indeed we're using a custom less transform in our conference planner application, but these extensions are generally not well supported and there's not much of a community around them. You can't find that many custom script bundle transforms on the web. Another part to this is that the code to create the bundle forms part of the application, so it's actually code that's compiled into your running web application. Now this isn't a big deal, but again it's a little bit of minor code bloat, that whole web optimization package with all of its minifiers and bundlers and transforms becomes part of your application's memory footprint. Finally it's worth noting that the new ASP.NET Core system doesn't support system web optimization anymore. This doesn't exist anymore in ASP.NET Core. They're going in a different direction, more in line with the task runner approach that we'll see in a second. So how does all this look in our new world of task runners and module bundlers? Well, the bundles are defined in JavaScript files or in JSON configuration files, depending on the tool. The bundling happens at compile-time always. So all of these tools run at compile-time as part of your build, none of them attempt to build the bundles at runtime. They are easily extensible with a rich ecosystem that has a wide variety of available plugins, so no matter what type of file you're trying to bundle, you'll be able to find an extension for these tools that will bundle it for you. And to reiterate the fact that because the code always runs at build time, the code that performs the bundling and minification does not form part of your compile application, it's simply a build tool that gets run as part of your build process and it never makes it into the running applications app domain. There are a couple of other benefits of using these tools, such as module bundlers which can automatically trace JavaScript module dependencies, which we'll touch on later on in this module. And a lot of them provide extra features such as hot reloading where you can update one of your JavaScript files and they will automatically update it in the browser.
Task Runners
So what is a task runner? Well it's a tool that allows you to automate the running of a sequence of tasks and specify dependencies between the tasks. Now you might be thinking, well isn't that just what a batch file or a PowerShell script does? Well in a sense yes, but the real beauty of the task runners is the number of plugins they have. So there's a massive ecosystem of plugins for these task runners, which provides specific functionality, such as transpiling TypeScript, such as minifying JavaScript, there's such a large array of these task plugins that you can download that often you need to do very little work to get them set up to produce exactly the output that you're looking for. These are usually used as part of the app build process, of course, task runners are fairly generic so you can use them for all sorts of things. But in the context that we're looking at them, you'd usually tie them into your application build process. Grunt and Gulp are the most popular of these tools on the market today. So let's look at them in more detail. Grunt was the first one on the scene back in 2012. It is configuration-based. That is, you define a JavaScript object that lists all the tasks that you want and their configuration properties. You then tell Grunt which task or set of tasks you want to run. If you want to pass some data through multiple tasks, Grunt has traditionally used intermediate files in between them. For example, if you wanted to concatenate and then minify some JavaScript, Grunt would run the concatenation task, which would produce a temporary file and the minification task would then read that temporary file and produce a final output, which was concatenated and minified. Grunt runs on top of Node.js like many other build tools and it integrates with Visual Studio's Task Runner Explorer. Gulp was first released in 2014, so a couple of years later. It uses code based tasks, that is, instead of having a big JavaScript configuration object. Each task is a JavaScript function and the content of the task is defined with JavaScript code. One of the other improvements that Gulp made was the use of pipes to send the output from one task to the next, so instead of writing temporary files, Gulp would pipe the output straight from the first task into the second task. This meant that when Gulp was released, it was significantly faster than Grunt. Gulp also runs on Node.js and also integrates with Visual Studio's Task Runner Explorer. So which one are people using? Well as we can see in this Google Trends graph, Grunt had a head start because it was the first one to be released, but then Gulp started catching up quickly and Gulp took the number one spot around the end of 2015. Since then though, both have been a little bit in decline and the reason for that is something we'll cover later in this module. Now if you're choosing between Grunt and Gulp, part of the decision is where you prefer to specify your tasks with configuration, as in Grunt, or whether you prefer to use code, as in Gulp. Gulp used to have a performance advantage, but Grunt have no implemented piping as well in the latest version, so this is no longer a deciding factor. Both have a massive ecosystem of plugins where you can find a plugin to do almost anything that you need.
Demo: Grunt and Gulp
Okay, so let's dive in and see what Grunt and Gulp look like as part of the conference planner application. Here we've got our trusty conference planner application open again in Visual Studio. What we're going to do is replace the script bundle that we've got here with a Grunt or Gulp method of doing the JavaScript concatenation and minification. You can see here that I've added two new files to the solution, the gruntfile.js and a gulpfile.js. Now normally you wouldn't have both of these in the solution, you'd use one or the other, but here we've got both so you can take a look at them side by side and contrast them. Let's start by opening the Grunt file. Here you can see that Grunt, as we said earlier, is defined by configuration. So here is the large configuration object being passed into Grunt's initConfig method. And you can see here we define a concat task, an uglify task, and if we scroll down a bit, a watch task as well. If we scroll down further, we can see that we make a few calls to Grunt to load npm tasks, this tells it to load in the tasks defined in those plugins, and then at the bottom we call registerTask and this is to register tasks that are composed of multiple subtasks. So for example, our build-js task is composed of a concat and an uglify task. If we open the gulpfile.js, here is the same thing in Gulp. At the top we've got the requires for the plugins that we're using, in this case concat and uglify, and then underneath we define a build task and a watch task. You can see in the build task we first of all find all of the JavaScript files and then we pipe them into the concat plugin, which concatenates them altogether and then we pipe that into the uglify plugin, which minifies the output. Finally, gulp.dest tells it to write the file to that destination folder. In both the Gulp and the Grunt files we've also got a watch task. The watch task is something that Gulp and Grunt both support, you tell it a file specification that it needs to watch and then if any of those files change it will rerun the specified tasks. This is great when you're doing development because as soon as you make a change to one of your local JavaScript files, the build task will rerun and recreate your combined output file for you without you having to do anything. There are even some live reload plugins you can use as well, which will make the browser automatically refresh in this situation, saving you from even having to click the refresh button. So how do we run these tasks? Well we can run Grunt or Gulp at the command line, but we can also use Visual Studio's Task Runner Explorer. If we right click on one of these files, we can see we get an option Task Runner Explorer in Visual Studio. The Task Runner Explorer supports both the Gulp file and the Grunt file and it lists all the tasks within them. For example, here if we look at our Gulp file we have a watch task, a build-js task and a default task. And you can see them all reflected there in the Task Runner Explorer. All we have to do then is right click one of them and click Run. In this case I've started the Gulp watch task. So this watch task will now just run in the background and if I change one of my JavaScript files, for example, let's open this and let's just add 100 to our attendee count. When I save the file, you can see in the Task Runner Explorer that Gulp has automatically run the build-js task. Another feature of the Task Runner Explorer is bindings. If we right click on a task, we can see we've got some binding options and the options are before build, after build, clean and project open. Before build and after build are very useful for tying in tasks such as our build task because whenever we build our .NET application we probably want to rerun our Gulp task to rebuild our JavaScript output. The project open option is very useful for watch tasks. That means that when we open the project in Visual Studio, if we bind the watch task to the project's open action, then Visual Studio will automatically run the watch task for us when we open the solution. That's very useful because then the watch will constantly be running in the background and all we have to do is update our JavaScript files and we don't have to think about it. Let's go back and take a look at the code that we're wanting to replace. If we remove our JavaScript script bundle from the code, then we also need to update our layout page that renders it. Currently this layout page renders the script bundle using the standard .NET framework method. Now that we're using a task running instead, we need to replace this with a reference to the file that the task runner has generated. So, the obvious option is to simply do this. So we put in a direct reference to the output file that Gulp has generated. However, by doing this we've lost two major features of the .NET script bundler. One is the cache busting functionality whereby it appends a hash to the end of the query string so that the browser will automatically redownload the file if it changes. And the other thing we've lost is, when we're in development mode, the ability to debug the individual files in the web browser rather than the minified file. To get that functionality back, we need to add a little bit more to our task runner definitions. Now I'm just going to do this in Gulp as a demonstration, but it's possible to do a similar thing in Grunt as well. It's worth noting at this point that if you've got an ASP.NET core application, this is actually a lot easier to do. There's an asp append version tag helper that can append the hash for you and you have the environments tags that you can use to have different HTML in debug and release mode. But as we're integrating with an ASP.NET 4.5 application, we're going to have to do this the harder way. We're going to use a Gulp plugin called Gulp-inject. Okay so the plugin's been added. Gulp-inject allows us to put some comments in our HTML file and then it will replace the content of those comments when we run our build and voila, I've added them. These comments instruct the gulp-inject plugin to replace the HTML between these comments with whatever it generates when it runs. Heading back to the Gulp file, we need to make a few changes. Okay, those changes have been made. What we've done here is we've added a reference to the gulp-inject plugin and then we've specified our injection options. Here we've got a prefix of the tilde, this is to make sure that the URLs we generate start with the ASP.NET tilde in the URL. We're telling it not to add the rootSlash because we don't want the URL to start with a slash, we want it to start with a tilde. And in our suffix, we're generating a timestamped query string. This will provide us with cache busting functionality, similar to what was provided before by the .NET framework script bundler. If we scroll down, we can see that we've added a couple of new tasks, an inject-dev task and an inject-prod task. Both of these tasks reference the layout cshtml and use the inject plugin to inject the script tags. In the dev scenario we find all of the JavaScript files in the application and inject their URLs as separate script tags. In the production scenario, we simply inject the combined minified JavaScript file that we produced from our build task. It's worth noting here that injecting directly into the layout page is not ideal. For example, if you're using source control, it will keep creating pending changes. But this is just the simplest way to illustrate the point. Okay so let's see if this works. Let's open the Task Runner Explorer and let's run our inject-dev task. Okay let's have a look at the Layout.cshtml and we can see, yes the reference that we put in there has been replace with three direct references to our individual JavaScript files along with the cache busting tag. Now let's try our inject-prod task. And yeah, there again you can see it's replaced it with a direct reference to our minify JavaScript file along with a cache busting tag again. Let's see if this works. And yeah, it seems to be working. Yep we can click the link and we're good. Now we've gone to quite a lot of effort here to just replicate what the .NET functionality provides. It's a fair bit of work to set this up and we've ended up in the same position we were to start with. But the situation we've created for ourselves now means that we have an easily extensible Gulp pipeline. Here if we need to transpile TypeScript or JSX, if we want to do some JS hinting, if we want to run some unit tests, we've got a pipeline here that we can add all of that into very easily. So this is really just the starting point that now allows us to have a much more extensible build process.
Module Bundlers
Now let's take a look at module bundlers. So module bundlers are tools which walk the JavaScript module graph and find dependencies. You give then an entry point, you tell them which is your top level JavaScript module, and they will then follow all of your require statements, your import statements or your defines, they will follow those and they will walk through them creating a graph as they go of all the modules that are in use within the application. They will then bundle all of those together into output files, so much like the concatenation and minification process that we did with Gulp, module bundlers will do a similar thing, but they will only do it with the JavaScript files that they picked up by walking the module tree. The difference between the module bundlers and the task runners is that the module bundlers are much more opinionated around a specific task. So whereas the task runners like Grunt and Gulp are very generic, and you can use them for almost anything. The module bundlers are very specifically designed around web applications and about creating combined and minified files for the browser. And the result of this is that they require less configuration than Gulp or Grunt because they make a certain set of assumptions about what you're trying to do to start with. The module bundlers can also be extended with plugins to process additional formats, so although they make assumptions about JavaScript and CSS to start with, you can still add extra plugins to process other formats, such as LESS and SASS and TypeScript and Babel. Webpack and Browserify are the most popular of these module bundlers in use today. So let's take a look at them in more detail. Browserify was first released in 2011. It was actually designed to allow Node.js applications to be run in a web browser, as well as concatenation and minification of the files, Browserify's other main feature is providing simulations of the common Node.js APIs within the browser. Initially Browserify only supported the CommonJS type of modules, as this is the standard with Node.js, but nowadays it supports AMD modules as well. Webpack is a more recent entrance onto the scene. It was designed specifically as a tool to bundle up your assets for use in the web browser. So it has no particular ties to Node.js and it's specifically designed for producing web applications and preparing them to run in the browser. Webpack supports tracing dependency trees using the CommonJS modules, AMD modules, and also the new ES6 module syntax. Now module bundles don't just work with JavaScript, of course, they're also able to bundle up CSS and images and any other assets that your web application requires. So let's look at one of our trustee Google trends graphs. As we can see here, Browserify's popularity has been on decline since Webpack arrived. You can see here that since Webpack was released in 2014 it's had a steady increase in interest and it's probably fair to say that Webpack is the most popular bundler in use today.
Demo: Webpack
Let's have a look at how we might use Webpack in our conference planner application. So here we are back in Visual Studio and this time I've updated the conference planner application to use Webpack. Let's have a quick look at what we've done. If we open the global.asax we can see that the RegisterBundles method is now empty, so I've removed all the code that used to be there to create our script bundle and style bundle. We can also see that we've got a new file, webpack.config.js. Looking inside this file we can see the Webpack configuration. The top of the file is not so interesting, so let's scroll down to the main configuration object, which is here. So what are a few of the key points here? Well, first we have an entry property. This specifies all of the entry points that Webpack should consider. We're just defining a single entry point called app. For each entry point that you define, Webpack will produce a separate bundle and in our case we only want a single bundle for our small application. Remember that Webpack is a dependency walker, so you tell it where to start and it then automatically goes and follows all the dependencies. So here we've giving it two places to start, the startup.js file and the app.less file. As you can see, Webpack deals with JavaScript and other types of files in the same way. Next, we have an output section. Here we tell Webpack where to put the output and how to name it. The path defines the folder that we want the files to be output into. The filename defines the way we want it to name the files and you can see we've got the hash on the end of the query string as a cache busting mechanism, and the publicPath, which is a URL by which the files will be downloaded by the browser. Next we have the module section. This tells Webpack which types of files we're going to process and how it should process them. By default Webpack understands JavaScript, but it doesn't understand anything else. For all other types of files you need to use loaders. These loaders are simply npm packages that you install with npm install. Here we've specified that for less files it's going to use three loaders and the loaders are run right to left. So first it will run the less-loader, that converts less into CSS. Then it will run the css-loader, that converts CSS into a JavaScript format that Webpack can work with. Finally, the style-loader is a loader that takes those styles and injects them into the webpage. Finally, we have the plugin section. Here we're using a plugin to inject the bundle URLs into the output HTML, much like we did with Gulp, but here instead of injecting in place you need to specify a different output file. So what I've done is renamed the old Layout.cshtml to Layout_src and we're telling the plugin to generate the Layout.cshtml as its output. This is a slightly hacky thing to do because we want Webpack to work nicely with our existing application. If you were starting a new application from scratch, you would probably have a static index HTML file and not use a razor.cshtml for this. The inject property tells it where it inject the tags, in this case I'm just telling it to inject them into the head tag on the page. Let's take a quick look at our renamed Layout_src.cshtml. You can see here that we've remove the rendering of the script bundle on the style bundle, so now there's no reference to our scripts or our styles in this file. Finally, the other changes is in startup.js. Remember that Webpack is a dependency walker and we've pointed it to the startup.js file, but because startup.js is not actually a module, startup.js is not an AMD module or a CommonJS module, Webpack doesn't understand it so it's not able to follow any dependencies. Here we've manually specified our index file and our conferenceListItem.controller as dependencies using the require method. Now this changes obviously easy in our sample application, but if you were applying this to a real world existing ASP.NET MVC application, this would be an extensive change, therefore using a module bundler that walks dependencies is a difficult thing to integrate into a legacy application. Going through and specifying dependencies between files is a time consuming process if they don't already exist. If the application has been written using modules to start with though, this is a lot less painful because a lot of it will already be in place. So with that done, let's run Webpack and see what happens. Okay that all seemed to work, let's see what it's generated. If we switch and show all files in the Solution Explorer, we'll see that this Layout.cshtml has reappeared. And in here we can see that it's emitted a script tag. Just one script tag though, what happened to our styles? Well it turns out the styles are actually bundled into the JavaScript file as JavaScript. So the way we've set it up, if we now run the application and have a look in the browser, we can see that Webpack has created some JavaScript to inject our CSS directly into the header tag of the page as a style tag. Now that's great, but probably not what we want in a production application, so for a production release we want to output this as an actual separate CSS file instead. To do that we need to use something called the ExtractTextPlugin. So I'm going to update our Webpack configuration now, and there we go. We've added a reference to the ExtractTextPlugin at the top, and then if we scroll down there's a couple of changes here. First we're referencing the new ExtractTextPlugin and we're specifying the output name of the CSS file, along with the hash and the query string. And then in the rules for processing less files, we're telling Webpack to pass the content through the less-loader, then the css-loader, and then pass it into the ExtractTextPlugin, which will create a separate CSS file with the content. Let's give this a try. Okay it all seemed to work. Let's have a look in our Layout.cshtml. And yep, we can see we've got a JavaScript file and we've also got an app.css as well. Now Webpack is a very powerful tool. It offers a lot of other features that we haven't looked at, such as live reloading, where it can automatically reload your JavaScript and your styles as you change them without having to refresh the page, but bear in mind that Webpack and module bundlers can be relatively difficult to integrate into an existing application, but if you're starting a new application from scratch, definitely worth thinking about.
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.
Module Summary
So what have we learned in this module? Well we've learned about how task runners, like Grunt and Gulp, allow you to automate common build tasks and they're pretty flexible at allowing you to set up some pretty complex build chains with enough plugins available that you can achieve almost anything that you need. We then looked at module bundlers and saw how they were different to task runners. We've seen how their focus is to dependency walk you JavaScript modules and produce bundles as an output. Finally, we've talked a bit about using npm as a task runner and how the latest trend is using the Webpack module bundler with npm as a task runner. Of course, as usual, we've barely scratched the surface of these task runners and module bundlers. If you want to learn more, I'd recommend taking one of these Pluralsight courses, which goes into more detail and allows you to have a deeper dive into these technologies.
Conclusion
Course Summary
Congratulations, you've made it through to the end of the course. In this module we're just going to recap everything that we've talked about in this course so that we can reflect back about the things that we've learned and where we go from here. So the first thing we talked about was package managers. And we said that package managers handled downloading and installing your front end dependencies for you. So we talked about how it means you don't have to go and find where to download it, you don't have to figure out how to install it, the package manager takes care of all that for you. We also talked about how package managers manage updates and dependencies of the dependencies. If you install one package, the package manage will automatically install all of its dependencies as well, so you don't have to deal with that yourself. As part of that, we learned about how Node.js is a command-line JavaScript runtime that many of the tools in this course depend on. The specific package manager tools that we talked about were npm, bower, and yarn, and we said that npm is probably the most popular one, but we said that yarn is a newcomer that improves on some of the issues using npm within a team environment. Next we talked about transpilers. We learned how they allow you to convert modern JavaScript code into older JavaScript versions that can run in a browser. And we learned about how they allow you to add additional language features, such as the way TypeScript, for example, provides typing support or CoffeeScript provides an entirely different language altogether. The particular tools we talked about were TypeScript, Babel, and CoffeeScript. Then we moved on to talk about JavaScript modules. We learned about how they allow you to avoid global variables in your JavaScript code and how they allow you to specify dependencies between code files. This results in code that's better structured and easier to follow. We talked about how RequireJS is a common tool for using modules in the browser environment, we talked about how Node.js implements the CommonJS specification for modules, and we talked about how TypeScript and Babel can allow you to implement ES6 modules in your JavaScript code. After that we moved on to talk about front-end frameworks. We learned about how the data binding takes care of updating the DOM for you, which means that you avoid having brittle jQuery code in your application. And the result is faster development because you don't need to write loads of manual hard coded jQuery statements to update parts of the page, the data binding just takes care of it all for you. In particular, we talked a bit about Angular and React. Finally we concluded by learning about task runners and module bundlers. We learned how they allow you to bundle your web assets for production, but also how they have additional features to speed up development, such as live reloading and hot module replacement. The particular tools that we talked about were Grunt, Gulp, Webpack and Browserify. Now throughout this course we've only been giving you a very high level overview of these different tools and technologies. But now that you've learned a bit about them all, I'm sure there'll be some of these tools that you want to learn in more detail. In each module we suggested Pluralsight courses that could help you with that, so refer back to the summary slide in each of the modules, but also just search Pluralsight for the tools that interest you and by doing so you can dive deeper into these technologies and learn more about them. Thanks for watching and I hope you've found this course useful.
Course author
Chris Jones
Chris has 15 years of commercial software development experience, in recent years having a particular focus on ASP.NET Web Development.
Course info
LevelBeginner
Rating
(59)
My rating
Duration1h 50m
Released13 Jun 2017
Share course