Upgrading to Vue 3 when using .Net Razor views

A follow up on my previous post on how to integrate Vue.js into Razor views

Posted on December 19, 2020


In my previous blog post about integrating Vue into Razor views, I showed a fun way to work with Vue.js while still leveraging the best and robust way of building a server side rendered webapp with regular Razor views.

In the meantime, Microsoft has launched a new version of .Net which tries to align the .Net ecosystem onto a more direct path forward, which is pretty nice, and Vue has launched a new version with breaking changes - Vue 3.

Upgrading to Vue 3 can be more of less an investment in time depending on the size and complexity of the frontend application. For small applications, it doesn't seem to be a big undertaking and is pretty straight forward.

However, I did spend some time trying to get Vue 3 to work when using it with Razor views and my Google skills could only find one pretty much unsolved Stack Overflow post, so I wanted to do a quick write up in case I forget how to do it in the future.

Without further ado, let's go.

How to upgrade Vue 2 to Vue 3

0) The starting point

We'll start of with the project from my previous blog post which is a simple .Net core 3.1 MVC web app using Vue 2. The code can be found here at github. I've created a separate branch with the finished upgrade aswell.

1) Upgrading Vue packages

Upgrading the packages are rather simple and can be done like this. These are the newest package version as of writing this post.

Vue 3 package upgrade

Now install the packages with

npm i

If you would try to build the Vue app with "npm run build" now, you'd get compilation error in main.js. We will fix this in the next steps.

2) Restructuring main.js

Because Vue 3 has breaking changes in main.js, we will need to do a quick rewrite of this file.

vue 3 mainjs upgrade

As you can see, instead of using the "Vue" object we will now import "createApp" from vue and register our global components a little bit different. We will also not bind Vue to the window element anymore. This was not necessary before either though. So go ahead and remove this line in _Layout.cshtml also, it looks like this.

<script>new Vue({}).$mount('#app')</script>

3) Making Razor views work

We still get a compilation error when we try to "npm run build" in our application. This is due to the way we have aliased vue. Because we want to be able to use Vue components directly in the markup in our Razor views, we need to specify the correct reference of vue. We did this in our vue.config.js file and we need to update this:

alias: {
  vue$: "vue/dist/vue.esm-browser.prod.js",

Now we should pretty much have a working setup, except, we have another breaking change in the project.

4) Replacing our event bus

In the previous blog post I also showed how to communicate between "top level components", which are the Vue components we reference directly in our Razor views. We did this be defining a new instance of Vue and using this "bus.$on" and "bus.$emit". However, this way is not supported in Vue 3.

This was not officially supported by Vue in the previous version either, but none the less perfectly fine for small projects. To overcome this challenge we could use something like "VueX" which I would recommend. But if we want to keep it simple and not do too much refactoring in our current project, we could use the mitt library to dispatch events between components in pretty much the same way.

To do this we install mitt like so and add it to our main.js so it would look like below.

npm install mitt --save

// main.js
import { createApp } from "vue";
import DemoComponent from "./components/DemoComponent";
import DemoEventComponent from "./components/DemoEventComponent";
import mitt from "mitt";

let app = createApp({
  components: {

const emitter = mitt();
app.config.globalProperties.emitter = emitter;

Now we want to modify our demo components and replace the logic which used the "vue bus" with the mitt emitter we wired up in main.js.

The snippets here are the new code in the demo components.

// DemoEventComponent.vue -- The publisher
click: function() {
  this.emitter.emit("demoEvent", this.timesClicked);

// DemoComponent.vue -- The subscriber
created() {
  this.emitter.on("demoEvent", (clickCount) => {
    this.eventMsg = `Clickcount on button in another component: ${clickCount}`;

With these changes we are all set.


And that's all. Now you can compile the project with

npm run build

And the app should be good to go. Pretty straight forward. Enjoy the new version of Vue. Don't forget to check out Vues documentation of the new features.

You can also run the webapp and you should see this screen with everything working just as before the upgrade.

dotnet run



In this short blog post I've showed you how to upgrade to Vue 3 when already having an existing .Net webapp with Vue components in your Razor views.

While this is pretty straight forward there are some breaking changes, and because we want to use Vue components directly in our Razor views, we have a little extra work to do. We also saw that we can't use Vue as an event bus anymore. To fix this issue we used a 3rd party library called mitt which was almost a drop in replacement.

The before and after code is available at Github.

Jeppe Ærenlund profile image

About the author

Jeppe Ærenlund

I'm a former social worker who decided to switch to a tech career. Today I'm working as a specialized .Net backend developer and learning new stuff every day. I like to keep active and I hope this blog can help inspire new developers aswell.

If you liked this blog post consider supporting me by bying me a coffee.