I’ve received some (constructive) criticism on this article, and it was warranted. There’s a few things I should have been more clear on up-front.
Second, I should have mentioned earlier in the piece that the second half of the article is devoted to explaining the work I did in finding a viable .NET Core 2.1 / Vue.js setup. If you aren’t interested in commentary about Vue/.NET, please — scroll down. Additionally, I’ll be expanding on that portion significantly in the coming days. I definitely could/should have made that section more robust.
Per Steve Sanderson’s blog:
“What is Blazor? It’s a framework for browser-based (client-side) applications written in .NET, running under WebAssembly. It gives you all the benefits of a rich, modern single-page application (SPA) platform while letting you use .NET end-to-end, including sharing code across server and client. The announcement post covers more about the intended use cases, timescales, and so on.”
I’m extremely excited about Blazor — it looks like it could be the missing piece to fill the void that Razor pages/Jquery used to occupy.
Finally, I just wanted to thank everyone that has commented both here and on Reddit. The feedback I’ve received has been well-taken, and will be considered moving forward. I’m choosing not to alter my original piece — I’ll let it stand, even if in hindsight some of my opinions could have been more deeply considered.
Thanks for reading.
The State of the SPA in .NET Core 2.1
First, a little background: I work in a medium-large-sized corporation’s development team. We run a traditional MVC 5 stack backed by SQL, with a Vue.js front-end. It works, but it hasn’t been without its headaches. Despite the issues, we are sticking with Vue, and are preparing to upgrade to Core 2.1 over the Winter holiday.
In preparation for our upgrade from MVC 5 to Core 2.1, I’ve been doing research on my own time — getting familiar with changes and determining where potential roadblocks may occur.
The collection is made up of three NuGet packages:
- Microsoft.AspNetCore.NodeServices (NodeServices)
- Microsoft.AspNetCore.SpaServices (SpaServices)
- Microsoft.AspNetCore.SpaTemplates (SpaTemplates)
Each of these packages provides new features and are extensible in 2.1 in ways that weren’t possible or nearly as practical in previous releases. If you’re at all familiar with SPA development in .NET Core, you’ve probably already used one or all of these packages.
If you’re just getting started using the SPA features in .NET Core, run
dotnet new — -install Microsoft.AspNetCore.SpaTemplates::* . The SDK comes with templates for React and Angular by default — this will install the rest of them. Once you have the full suite of templates installed, run
dotnet new -l to view them.
I was happy to see that the larger collection contained a template for Vue.js. After running
dotnet new vue and allowing the project to scaffold, I entered the ClientApp/package.json to inspect the bones of the project. I was disappointed, however, to find that most of the project’s dependencies (Webpack, Babel, etc.) were fairly dated. The template’s Webpack version, for instance, is 2.7 (current is 4x).
All of this is okay and the project runs, but there’s no question that you’re absolutely missing out on some of the most modern features of these dependencies.
Out of curiosity, I decided to scaffold a React project using the
dotnet new cli. To my surprise, the React template’s dependencies were more or less completely up-to-date. Digging deeper, I found the cause of this discrepancy: Microsoft ended official support for Vue.js back in February, with Steve Sanderson stating the following:
Microsoft.AspNetCore.SpaTemplatespackage never shipped in the .NET Core SDK, and never reached an official level of support. The ASP.NET team's development resources are finite, and we think we can deliver more valuable features to ASP.NET developers by focusing elsewhere.
Microsoft.DotNet.Web.Spa.ProjectTemplatespackage, containing Angular, React, and React+Redux templates, is not affected. This ships in the .NET Core SDK and is officially supported. We continue to invest development effort in this package. We can put more time and effort into these SPA templates now the effort isn't so spread out.
Microsoft.AspNetCore.SpaTemplatespackage, containing Aurelia, Knockout, and Vue templates, continues to be available, but we'll no longer update it or work on issues related to it.
We encourage enthusiastic community members to ship your own
dotnet newtemplates. The
dotnet newsystem is extensible for this exact reason. If you want to own the go-to Aurelia/Knockout/Vue project template, now's your chance! You could fork the ones from
Microsoft.AspNetCore.SpaTemplates, or start from scratch depending on what you prefer.
I know this will be irritating to some people, especially those who have worked on PRs for the Aurelia/Knockout/Vue templates. I’m sorry about that! I hope you can understand that our goal is to offer the overall maximum benefit for ASP.NET developers based on the resources available.
Angular and React are without question leaders in the field — but Vue.js can no longer be placed into a category beneath either one of them. Vue has surpassed React in stars on Github, and while stars on Github do not equal commercial adoption, it’s becoming increasingly difficult to argue that Vue doesn’t deserve a spot at the big boys’ table. Just how “dominant” does a framework need to become to win back official support from Microsoft? What is the metric used to measure a framework’s dominance? How pervasive and ubiquitous does a framework need to become before it can be recognized as being a worthwhile investment of Microsoft’s resources?
Looking below at this Google Trends comparison displaying interest over time, it’s not difficult to see Vue’s increasing popularity (Vue in Blue, React in Red):
Again, I’m not asserting that search term comparisons directly qualify legitimacy nor adoption, but they do provide a window into the public’s increasing appetite for Evan You’s creation.
Occam’s Razor dictates that the simplest explanation is most often the correct one. To me, the most simple explanation for Microsoft’s dropping of official support for Vue.js (in the face of a meteoric rise in popularity), is not just due to a lack of resources, or the threat of a future wane in public interest — it’s because Vue isn’t backed by a fellow massive corporation.
Angular (Google) and React (Facebook), despite outward appearances, must inevitably view (pun) Vue.js as a competitor encroaching on their respective market share. Could an alternative explanation for Microsoft dropping support for Vue be corporate allegiance? I certainly think it’s possible. Am I saying there’s a deep-seated conspiracy at the highest levels of Microsoft’s .NET leadership to slow Vue’s ascent? No. I’m just saying it might be a correlation worth noting.
These requests, unfortunately, are not something my team can wait on — we need to upgrade to Core. The lack of a modern Vue.js template, and the fairly small breadth of documentation for enterprise-size projects running Core and Vue at scale aren’t ideal, but we are forging ahead nonetheless.
A Modern Vue.js Template Of Our Own
One of the first questions I had after digging into the SpaTemplates project was whether or not there were any viable community-made alternatives (as suggested by Microsoft) available today that could function as a viable stand-in for Microsoft’s now-defunct offering. There are a few available on Github, though only one stands out in my mind as being a decent starting point for a modern enterprise-grade SPA — this one. Mark Pieszak’s template simplifies and adds onto the existing setup from MS.
The only downside I ran into, however, is that Mark’s template is still running some older dependencies, similar to Microsoft’s. Webpack, for instance, ships in this template @version 2.7 (though there is an open issue related to upgrading to 4). Webpack 2.7 definitely functions, but due to build sizes in CI, my team requires some of the newer features made available in Webpack 4.
To solve this issue, I used Mark’s template as a starting point, and altered/expanded upon it. Instead of manually upgrading Webpack to version 4.x (which I’ve done before and can be a slog), I decided to see if I could get it to work with @vue/cli3.
Vue’s CLI is an absolutely amazing tool — its scaffolding features, plugins, testing capabilities, and ease-of-use are second-to-none.
To my surprise, it wasn’t too difficult to get a new template working that utilized vue-cli and .NET Core 2.1 — see it here.
My template contains a solution with a Presentation Layer with a mostly empty project scaffold, and a DAL (Data Access Layer) with some dummy Models/Contexts. The solution’s
nuget restore includes Entity Framework core (my use-case utilizes SQL server), although you may absolutely remove EF/the entire DAL if you’d like.
You’ll likely notice that the solution’s Presentation Layer is missing some pieces — this is where vue-cli comes in. After cloning the repository, navigate to the Presentation Layer’s root folder, by default named ‘VueCLICore.’ Once inside, you’re ready to begin the vue-cli scaffolding process.
Disclaimer: the following assumes that you already have vue-cli installed globally on your machine. To do so, run
npm install -g @vue/clifrom your machine’s root (or anywhere). Once installed, we’re ready to resume the process:
From here, there are two separate, but similar, paths that we can take. We can use vue-cli’s features via the command line, or use the new vue-cli GUI (recommended). I’m normally a huge proponent of cli-based services, but the GUI is too awesome to ignore.
Vue-cli’s GUI contains full capability for project scaffolding, plugin installation, metric analysis, configuration of internals, as well as project administration commands, plus many other features. It’s a sight to behold, for sure. The following will assume that you are using the GUI:
- Open up a separate terminal, and run
vue uifrom any directory. This will start up the vue-cli GUI.
- Once inside the GUI, press the home button to ensure that you’re in the right place. Press the ‘Create’ button to start a new project.
- Navigate to your solution’s directory, and then to the Presentation Layer’s root (VueCLICore).
- Within the above directory, press ‘Create a new project here.’
- Important: Name the new project ‘ClientApp,’ and select ‘overwrite target folder if it exists.’
- Select your preferred package manager, and create the project.
- The following screen will allow you to configure the project. For the first time, at least, I would recommend doing this manually.
- While configuring the project, select add-ons and dependencies as you would like. For my project, I added TypeScript, unit and e2e testing, as well as support for Router, Vuex, and Stylus. Note: if you are planning on adding Vuetify as a plugin later, I recommend selecting Stylus at this stage (a dependency of Vuetify).
- When you are done configuring your project, either save the configuration as a preset (recommended), or continue.
- The project will now scaffold. If everything was done correctly, you should be able to see your new ClientApp folder from within Visual Studio/VS Code.
- After scaffolding, from within the terminal, run
npm installfrom within the newly scaffolded ClientApp folder. This will ensure that all dependencies have been restored/installed correctly.
From this point, you have a few options. If you are planning on adding additional plugins (Vuetify, Axios, etc.), I would recommend installing them now. Vue-cli will alter your solution’s files when installing plugins — doing this with a blank project will reduce the risk of breaking changes.
After you’ve finished adding plugins (or not), you’re ready to run your project. There are three ways of doing this:
- The project is configured to be run through IIS, complete with HMR.
Note: if running your project through Visual Studio’s IIS, there’s a couple of caveats to be aware of:
SSL must be turned off. Navigate to your solution’s properties (right click solution, Properties, Debug), and uncheck ‘require SSL.’
HTTPS must also be turned off. This has already been partially configured for you via
Startup.cs(removed the HTTPS method), but to be sure, make sure that the port you’re running IIS on (also found in Properties, Debug), is configured to run on
2. The project can be run via
dotnet run in the CLI. Navigate to port 8080.
3. The project can be run through
npm run serve via the cli or the vue-cli GUI (in build tasks). Navigate to port 8080.
The final note I’ll make on running the project also concerns IIS. When running through IIS, the project is configured to use vue-cli’s build process, and then listen on port 8080 for the built project. Sometimes this process doesn’t go as planned. If you encounter errors describing a timeout, close the window and run IIS again. This is a pain, but the project will typically load, complete with HMR, on the second or third attempt. This is a known issue that isn’t unique to vue-cli, and there may be workarounds (though none have worked for me to date).
Assuming everything went well, you now have a full-stack, multi-layered ASP.NET Core 2.1 application with vue-cli3, Webpack 4x (contained within vue-cli), and any other add-ons/plugins you opted to install.
Notes Regarding Template Installation
My template contains the templateconfig file/folder needed to install it as a new template for the
dotnet cli. If you would like to install it as a new template (for future use using
dotnet new scaffolding), simply type
dotnet new -i <path to solution> . Feel free to make any alterations/changes you desire before installing as a template.
Notes Regarding HMR (Hot Module Replacement)
A few notes regarding HMR and the project in general:
HMR has been an elusive beast for my team. As we currently run MVC 5 with LDAP/AD Windows Authentication, we haven’t been to get HMR working to date. Issues with the AD authentication have been prohibitive (CORS problems, timeouts, and a general lack of documentation for Webpack 4 with MVC 5 have been recurring issues).
With this project, and ASP.NET Core in general, large strides in relation to HMR have been made. The UseWebpackDevMiddleware method has improved .NET’s relationship with HMR.
Likewise, a big dependency of my template is a NuGet package called VueCliMiddleware. This package provides helpers that allow .NET to interact correctly with vue-cli — all of this probably wouldn’t be possible without it (not easily, at least).
As some of you may have gleaned, I’m still very new to .NET development, and development in general. Despite my fairly short tenure in my position, I’ve come to love working with .NET, C#, and the entire Microsoft ecosystem. My theory regarding Microsoft and Angular/React vs. Vue is just that — a theory.
My goal in writing that section of the article is not to discredit or defame Microsoft or anyone on the .NET/SpaServices teams — on the contrary, I’m extremely grateful for their work and the products they have built — I’m just hoping to see some more love for Vue.
Thanks for reading. If you have any questions — post them.