What a time to be alive, friends. As developers, we have a lot of options at our disposal when building a “modern” web application. Personally, when developing software, I like to consider all the tools available to me, but I tend to favor backend technologies more than frontend ones. Why may you ask? Generally speaking…
- Backend tools have a more straight-forward toolchain.
- Rendering server-side tends to lead to better performance.
- Access to more resources on the server (databases, caching, etc.)
With those advantages, we also have severe disadvantages:
- User interactivity can suffer or be non-existent.
- Perceived performance can suffer on multiple round trips.
- Increased load on the infrastructure can be costly.
Like all things in life, you should consider the trade-offs and act accordingly. But this post isn’t about compromises; it is about kicking ass and chewing bubble gum (bubble gum not included).
When you’re done reading this post, you’ll easily be able to take advantage of web components on your frontend, while leveraging the strength of ASP.NET Core for server-side rendering. To accomplish this, we’ll be using technologies Vue and Parcel, along with ASP.NET Core 3.0. This post is about setting up your application, so don’t expect any revelations around JavaScript or .NET (if that happens, then that’s great!).
ASP.NET Core Strengths
If you’re not familiar with ASP.NET Core, then let me have the Microsoft team explain what it is.
ASP.NET Core is a cross-platform, high-performance, open-source framework for building modern, cloud-based, Internet-connected applications.–Microsoft
I’d argue, most current web frameworks are pretty similar. If you come from any other ecosystem, many of the concepts you learned building for the web likely apply to ASP.NET Core.
In my opinion, there are strong arguments to use ASP.NET Core for building web applications. These arguments are:
- Building Web applications and APIs with a unified framework.
- Razor templating is a joy to work with and extend.
- Cross-platform development on Windows, macOS, and Linux.
- Performant HTTP pipeline.
- Open-source framework and ecosystem.
- Remixed UI approaches with Razor Pages or full-blown MVC.
Vue.js Strengths
Vue is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable.–Vue.js
Vue.js is, by far, my favorite frontend framework. Unlike other frameworks that either expect you to drink from a firehose of dogma or join some cult, Vue offers a simple approach to making your frontend more interactive.
Advantages from my perspective include:
- Incremental adoption is possible.
- A modern JavaScript toolchain is available.
- It has a declarative templating engine.
- Excellent documentation, through and through.
If you are familiar with working in Razor files, then Vue is a lateral tool, and you will find it a pleasure to work into your toolbox.
Parcel
While Vue.js development is possible without a modern JavaScript toolchain, you won’t get the best performance you can without adopting a compilation process. The default bundling and minification tools in ASP.NET Core are limited and incapable of handling and compilation.
There are many JavaScript toolchain options out there, but I wanted something that would work right out of the box with minimal setup. Parcel is an excellent choice for developers with a predominately backend experience.
Parcel is a web application bundler, differentiated by its developer experience. It offers blazing-fast performance utilizing multicore processing, and requires zero configuration.–Parcel
As you’ll see in the next section, the authors of the library can stand by that statement 100%.
Getting Started
From here on out, I’ll walk you through a step by step guide to creating an ASP.NET Core application. You will need several dependencies before starting:
Before we get started, I need to clarify something about the approach I am taking with Vue.
I am using a library called vue-custom-element. The library allows you to register any Vue component as a first-class web component. As you’ll see later in our example, you’ll be able to use these components just like any other HTML tag anywhere in your markup.
1. Creating Our ASP.NET Core Web Application
Once you have the .NET SDK installed, you can create a new ASP.NET Core web application. For this post, I chose the default web application template. It is an empty web application with bootstrap, jquery, and Razor pages. It’s very bare-bones.
2. Creating Our Packages.json File
To run our JavaScript pipeline, we will need a packages.json
file. The file will pull in our development dependencies and help us build our web components. Create a packags.json
file at the root of your project.
{
"name": "aspnetcore-vuecomponents",
"version": "1.0.0",
"dependencies": {},
"devDependencies": {
"@vue/component-compiler-utils": "^3.0.2",
"parcel-bundler": "^1.12.4",
"vue": "^2.6.10",
"vue-custom-element": "^3.2.10",
"vue-template-compiler": "^2.6.10"
},
"scripts": {
"build": "parcel build ./wwwroot/js/site.js --out-dir ./wwwroot/js/dist"
}
}
A few things to note about this file:
- All our dependencies are
devDependencies
. It means these are only required during the development process and not at runtime. - We include one script in the
scripts
section ofbuild
. The script will compile our Vue components later. - Parcel will be compiling our
site.js
file in our ASP.NET Core project and producing an artifact in thedist
folder.
3. Enhance The ASP.NET Core Build Process
To run Parcel, we need to modify our .csproj
file with a build target.
<Target Name="Parcel" BeforeTargets="Build">
<Exec Command="npm run build" />
</Target>
This build target will run our npm
script of build
in our packages.json
file on every build of our ASP.NET Core application. Here is the complete project file.
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<Target Name="Parcel" BeforeTargets="Build">
<Exec Command="npm run build" />
</Target>
</Project>
4. Writing Our First Vue Component
Our Vue component will be boring and straight-forward. It will spit out an <h2>
tag.
<template>
<h2></h2>
</template>
<script>
export default {
data() {
return {
message : 'Hello Vue Component!'
}
}
}
</script>
Place your component in a folder under our js
directory.
5. Registering our Web Component
To build our Vue Component and use it, we need to register it as a web component. In your site.js
file, add the following lines.
import Vue from 'vue';
import vueCustomElement from 'vue-custom-element'
import helloWorld from './components/helloworld'
Vue.use(vueCustomElement);
Vue.customElement('hello-world', helloWorld);
We are registering our helloworld
component with the name of hello-world
. Registering the component means any tag of <hello-world>
in our HTML will be converted into a Vue component when the page is done rendering on the client’s browser.
6. Let’s Use Our Component
The first step to using our new component is to make sure we are referencing our compiled JavaScript in our web application. In this case, our _Layout.cshtml
should have a <script>
reference.
<script src="~/js/dist/site.js" asp-append-version="true"></script>
Next, on any page where we have markup, we need to put our <hello-world>
tag. In this application, let’s put it on the Index
page.
@page
@model IndexModel
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<hello-world></hello-world>
</div>
If all goes well, you should see the following output.
7. Extra Credit
ASP.NET Core also has the concept of “View Components,” and this shouldn’t be confused with Web or Vue components. If you want to use them as well, and I recommend you do, the sample project I provided shows you how to write them.
The first step is to write a C# class that inherits from ViewComponent
.
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace aspnetcore_vuecomponents.ViewComponents
{
public class HelloWorld : ViewComponent
{
public async Task<IViewComponentResult> InvokeAsync()
{
return View();
}
}
}
The second step is to add a view of Default.cshtml
to your Pages
folder under Shared\Components\HelloWorld
.
<h2>Hello ASP.NET Core View Component</h2>
Finally, we invoke the ASP.NET Core component in our Index
page alongside our Vue web component.
@page
@model IndexModel
@addTagHelper *, aspnetcore-vuecomponents
@{
ViewData["Title"] = "Home page";
}
<div class="text-center">
<!-- HTML -->
<h2>Hello Safe and Familiar HTML World!</h2>
<!-- Vue Component : Rendered Client-side -->
<hello-world></hello-world>
<!-- ASP.NET Core View Component : Rendered Server-side -->
<vc:hello-world></vc:hello-world>
</div>
We get a result of all the things! Web Components, ASP.NET Core View Components, and good old HTML.
Conclusion
It can be daunting to utilize new technologies in your technical toolbox. It sometimes feels like different ecosystems battling for your mental capital. Sometimes it feels like it just might be easier to stick with what you know. What I showed you in this post is that you can utilize the latest in frontend technologies without investing a fortune in time and learning. Additionally, and what is most exciting is that many of these technologies are enhanced by each other and can help you build a better experience for your users. You can incrementally opt-in to creating the experience you want for you and your users when you need to.