Vuetify, from Webpack to Vite

A step-by-step guide on how to migrate your Vue2 with Vuetify project from Webpack to Vite

Jose Garcia
5 min readDec 7, 2022
Expresses transition from Webpack to Vite

I have a lot of legacy projects written in Vue2. And what styles library I use? Vuetify of course.

This article is designed to help you leverage the power of Vite. Because, even if you have legacy code, you deserve fast development times.

If you don’t need to support older browsers. If you want to speed up your development builds. If you want an overall better experience. You may want to take a look at Vite.

Vite has similar functionalities to Webpack. It bundles and compiles your code from Single File Components and Typescript to vanilla JavaScript.

If it does the same why would I want to use it?

Simple. The bundles produced by Vite are smaller. In practice this means 2 things:

  1. Faster development speed. As it has to produce less code it transpiles faster.
  2. Faster browser load speed. Smaller bundles load faster.

That’s an oversimplification, however. If you want to know exactly why you should use Vite take a look at this article:

Notes

  • Before we dive into Vite. You need to know that it does NOT support older browsers.
  • For this project I am using Vue2 and Vuetify2. Vuetify3 already has a Vite config that you can use.

Let’s do our migration.

Removing babel

On your package.json remove everything babel-related like so:

"@babel/core": "...",
"@babel/eslint-parser": "...",
"@vue/cli-plugin-babel": "...",

Delete the babel.config.js file altogether. It’s not needed anymore.

That done let’s remove the Webpack-related libraries.

Removing Webpack

On your package.json remove:

"@vue/cli-plugin-eslint": "...",
"@vue/cli-plugin-router": "...",
"@vue/cli-plugin-unit-jest": "...",
"@vue/cli-plugin-vuex": "...",
"@vue/cli-service": "...",

Notice that Webpack isn’t directly in the file. Instead is used “under the hood” by the @vue/cli packages.

Webpack and Babel removed. Now. Let’s add Vite.

Adding Vite

Install vite and vite-plugin-vue2 by running:

npm install -D vite vite-plugin-vue2

The first library is good old Vite. The second one is a plugin of Vite for Vue 2. Originally Vite was created to work with Vue3. This plugin allows Vite to do the same for the older version of Vue.

Rearranging the files

Vite is a little opinionated with our project’s structure of the files. We’ll have to change the directories of our static files.

Everything that was in the public folder, take it out to the root directory.

That “everything” I am referring to usually is:

  • index.html
  • favicon.ico

We need to do some changes to the index.html file. Otherwise, our project won’t work.

Changes to the index.html file

If you open your index.html you’ll find something like this:

<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

This has a problem. In Vite, we can’t use the template syntax.

In other words. Everything with <%...%> needs to go.

Once that is done we should have something like this:

<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="./favicon.ico" />
<title>Admin</title>
<script type="module" src="/src/main.js" defer></script>
</head>
<body>
<noscript>
<strong
>We're sorry but the admin doesn't work properly without JavaScript
enabled. Please enable it to continue.</strong
>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

Notice that we also need to add a script tag.

<script type="module" src="/src/main.js" defer></script>

This tells Vite where to put your compiled code.

Adding the Vite configs

In a similar vein to how we add configurations to Webpack, we need to do it with Vite.

A simple config file:

import { defineConfig } from "vite";
import { createVuePlugin as vue } from "vite-plugin-vue2";
import path from "path";

export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});

Let’s go step by step over this snippet.

First. We import the dependencies we need.

import { defineConfig } from "vite"

This is a function. With this function, we can define the Vite configurations.

import { createVuePlugin as vue } from "vite-plugin-vue2";

We are importing our vue2 plugin here.

import path from "path";

The path module. Good to resolve directory directions.

Now of to the hard stuff.

export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
"@": path.resolve(path.dirname(''), "./src"),
},
},
});

Notice that I am exporting defineConfig. This allows Vite to read our configurations.

plugins: [vue()],

Use the Vue2 plugin. This makes Vite able to use our Vue2 code.

resolve: {
alias: {
"@": path.resolve(path.dirname(''), "./src"),
},
},

If you enjoy your imports with the @ symbol you can define that aliases here. Notice that you can define as many alias as you need.

Add Vite scripts

We also need to update our scripts. From this:

"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},

To this:

"scripts": {
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"
},

With the configs so far you should have a working Vue2 with our Vite project.

Our configuration so far won’t work with Vuetify. We need some special tweaks to get this done.

Additional step

From now on. Whenever we import a Single File Component(SFC) you need to include the extension.

When before we could do this:

import HelloWorld from '@/components/HelloWorld';

Now we need to do this:

import HelloWorld from '@/components/HelloWorld.vue';

Eslint

For Eslint to work correctly with Vite we need to adjust some settings. If you don’t use it feel free to jump this section.

The usual babel/eslint config is something like this:

{
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "@babel/eslint-parser"
},
"rules": {}
}

We can fix this in 2 simple steps:

  1. In the env option go from node: true to es2021: true.
  2. Completely remove the parserOptions.

Now we have have this:

{
"root": true,
"env": {
"es2021": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {}
}

Adapt Vuetify to Vite

We have to install the following package to process Vuetify with Vite .

npm install -D unplugin-vue-components

After that, just add these configurations to vite.config.js.

import { defineConfig } from "vite";
import { createVuePlugin as vue } from "vite-plugin-vue2";
import { VuetifyResolver } from "unplugin-vue-components/resolvers";
import Components from "unplugin-vue-components/vite";
import path from "path";

// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
// Vuetify
VuetifyResolver(),
],
}),
],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
});

And we are done

Conclusions

  • Migrating from Webpack to Vite is not a big hassle. However, the increase in speed is worth it.
  • We don’t need Babel anymore.
  • Vite is opinionated regarding file locations.
  • Vuetify requires special configurations.

Fast is the new black my friends. Godspeed.

--

--

Jose Garcia

Hello There! I am a fullstack developer, a fan of open source and crypto and an obssesive fella. Well met.