While Vue 3 has been out of beta for quite a while, (as noted on their website) a migration build is still a work in progress so the current advice is to stay with Vue 2 if it’s a non-trivial project. I procrastinated on this article for so long that a migration build has since been released. Feel free to check it out here.
That said, as Parcel v1 is no longer maintained (and with v2 supporting only Vue 3), I figured it’s time to upgrade.
Why not Parcel v2?
This is actually quite straightforward. I’ve been wanting to try out vite for a while since I first saw it mentioned on an esbuild issue (asking for vue SFC support). I did consider snowpack for a while but I still decided to stick with vite seeing how its also created by Evan You and it seems to have mildly better performance.
I did initially try to upgrade the project to Parcel v2 seeing as how simple it was described as. However, I was wrong and instead of sinking anymore time into it, I decided to move onto something else.
Moving onto vite
The one thing that really sealed it for me (with vite) was how simple the move turned out to be. I created an empty project with their template, clone the relatively minimal default config over, and it’s “mostly” working. (Well, “mostly” because my project was still on Vue 2 instead of Vue 3.) Funnily enough, this was the same reason that led me to opting with Parcel initially since it needed very minimal configuration to get started.
According to the official Vue 3 guide, the way to call the router is to import and call it the
VueRouter you defined. This is slightly different from the previous version where you call
this.router to use it. Well technically you can still do exactly that, as long as you define router in your global properties like below.
At this point, router navigation should work just fine but you might see
vue-tsc) throwing type errors saying that
this.router is of type unknown. We’ll fix this later when discussing about
One of the main upgrades that Vue 3 provides is
vue-tsc. On top of the regular type checking already available with
vue-tsc also do type checking for inline TypeScript / Vue code in template (like
If you do your Vue project development on vscode, you probably have Vetur installed. While Vetur works with Vue 3 projects, Volar is an upgrade to that comparatively as it uses vue-tsc and displays those new type errors inline. They do not complement / work with each other though so make sure you remove one before you install the other.
So if you’re not already familiar with shims, it’s essentially a type declaration file to tell your IDE what are the types of the vue file exports (and tsx files). Here’s a stackoverflow question on why it’s needed.
This is the generic one that’d be generated when you create a new Vue project.
If you make router calls in your code with
this.$router directly, you might find
vue-tsc complaining about missing type declaration for it even if you already declared
app.use(router); in your
main.ts file. It seems like that doesn’t inherit the types imported automatically so you need to declare it separately for
vue-tsc to know where to look.
Of course, if you also call other stuffs similarly. As an example, let’s say you call
this.$notify with ElementPlus. You’d also include that in this type declaration file like this:
As for why I can’t just put these lines of codes in the same type declaration file as above, it threw me some error when I tried that. Separating them somehow solved the issue for me.
Usually this should just be in default state so the only change that needs to be made was to add this additional param of
type="module" to the script tag calling the entrypoint.
For pug in Vue 2, you can have your whole block indented (kinda like the regular html block). But in Vue 3, it’s no longer supported so your outer most
div can no longer be indented.
Overall, there are some bumps here and there but the process is relatively easy to understand especially with the help of new tools like volar (and faster compilation of vite).