Migrating from vue-cli to vite
April 29, 2022
Table of Contents
Why use vite
If you haven’t already heard of vite it is one of the new kids on the block for frontend tooling. It comes with a dev server and Javascript compiler/bundler and claims to rival the performance of tooling such as Webpack, Rollup and Parcel. It has really matured a lot in the last year or so and is growing in adoption, so much so that it has replaced vue-cli as the official tool for running and building Vue projects.
I recently went through the exercise of migrating a couple of our repos at Lob to using vite in place of vue-cli and the following documents the steps I took.
NOTE: these instructions are specific to Vue 3
Update vue
-
Remove
vue/compiler-sfcas it’s now already bundled in more recent versions of the vue core librarynpm uninstall @vue/compiler-sfc --save-dev -
Update vue to the latest
npm install vue@latest
Remove unneeded vue-cli dependencies
-
Remove unneeded vue-cli dependencies*
npm uninstall @vue/cli-plugin-babel @vue/cli-plugin-eslint @vue/cli-plugin-router @vue/cli-service sass-loader vue-loader vue-template-compiler --save-dev*NOTE: keep
sass-loaderif usingstorybook
Remove unneeded babel/webpack dependencies/config
-
Remove unneeded babel dependencies
npm uninstall @babel/core babel-eslint babel-loader --save-devnpm uninstall core-js -
Remove
babel.config.js -
(if exists) Remove
parser: "babel-eslint"fromparserOptionsin.eslintrc(or.eslintrc.js)
Update eslint
-
Update eslint and dependencies
npm install eslint@8 eslint-plugin-vue@8 --save-dev -
Update
eslintrcreplacingenv.node: truewith:"env": { "es2021": true }
Install vite
-
install vite library and dependencies
npm install vite @vitejs/plugin-vue --save-dev -
add a
vite.config.jsimport { defineConfig } from 'vite'; import vue from '@vitejs/plugin-vue'; const path = require('path'); // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': path.resolve(__dirname, './src') }, extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'] } }); -
add
jsconfig.json{ "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["src/*"] }, "sourceMap": true } }
Update index.html
(Skip if your repo is a library and not a standalone application)
- Move
index.htmlfrom/publicto the root of the project - Remove any
<%= htmlWebpackPlugin.options.title %>tags and replace with strings - Replace any
<%= BASE_URL %>tags with absolute paths - Replace
<!-- built files will be auto injected -->with<script type="module" src="/src/main.js"></script>
Update scripts in package.json
- Update
"serve": "vue-cli-service serve"to"dev": "vite" - Update
"build": "vue-cli-service build"to"build": "vite build" - Update
"lint": "vue-cli-service lint"to"lint": "eslint --ext .js,.vue ." - Add
"preview": "vite preview"
Update environment variables
- Everywhere that references
process.envneeds to be replaced withimport.meta.env - In environment variables replace all
VUE_APP_withVITE_ - Update special environment variables
Optional remaining clean up
- Add the
.vueextension to all single file component imports (if not using theresolve.extensionsproperty invite.config.js) - Remove any uses of
/* webpackChunkName: ...*/
Update build
(Skip if your repo is a standalone application, this step is for library packages only)
-
Configure “Library Mode”
-
Add the following to your
vite.config.js:-
Add to the
build.rollupOptionsobject:resolve: { dedupe: ['vue'] } -
Add to the top level
resolveobject:dedupe: ['vue']
(this is to prevent Vue from being bundled in the library package: https://github.com/vuejs/core/issues/4344)
-
Differences for a repo that uses Storybook
Because Storybook uses Webpack for running and building there are a couple of steps that need to differ for any repo that uses Storybook:
- Don’t remove (or add back if you already removed it) the
sass-loaderpackage - Add
vue-style-loaderto development dependencies (it was packaged with vue/cli-service previously so now it needs to be an explicit dependency)npm install sass-loader vue-style-loader --save-dev
Examples
Here I’m including a couple examples of the vite.config.js I ended up with for a library and
a standalone application:
Library
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
const path = require('path');
// https://vitejs.dev/config/
export default defineConfig({
build: {
lib: {
entry: path.resolve(__dirname, 'src/main.js'),
name: 'my-library',
fileName: (format) => `my-library.${format}.js`
},
rollupOptions: {
// make sure to externalize deps that shouldn't be bundled
// into your library
external: ['vue'],
output: {
// Provide global variables to use in the UMD build
// for externalized deps
globals: {
vue: 'Vue'
}
},
resolve: {
dedupe: ['vue']
}
}
},
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
},
dedupe: ['vue'],
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
}
});
Application
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
const path = require('path');
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue()
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src')
},
extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
},
server: {
host: true,
port: 8888,
strictPort: true
},
preview: {
port: 8888,
strictPort: true
}
});
Resources
The following are some helpful resources I used when performing these migrations: