CODEGURU

Переходим с Vue CLI на Vite

Зачем вообще переходить с Vue CLI на Vite?

Основная причина — скорость. Vite работает очень быстро, потому что использует нативные JavaScript модули. Дев-сервер запускается практически мгновенно. Но что особенно важно, обновление при внесении изменений в код также происходит моментально, независимо от размера бандла.

Для примера вот замеры скорости работы свежесозданного приложения на Vue CLI и такого же, но работающего на Vite.

  • Старт:

    • Vue CLI - 2591мс (более 2 секунд)
    • Vite - 259мс ( в 10 раз быстрее)
  • Обновление (HMR):

    • Vue CLI - 171мс
    • Vite - не выводит это время в консоль, но по ощущениям — моментально

И это новый проект, в котором, по сути, ещё ничего нет. По мере роста кодовой базы проект на Vue CLI будет работать всё медленнее и медленнее. А скорость работы проекта на Vite никак не изменится.

Как перейти с Vue CLI на Vite

Давайте смотреть на практике. Создадим проект на Vue CLI и переведём его на Vite.

Мы будем использовать Vue 2. Потому что с вероятностью 99% ваши проекты, созданные с Vue CLI работают на второй версии Vue. Но мы посмотрим как будет отличаться переход на Vite и для Vue 3.

Шаг #1: Обновляем зависимости

Нам нужно удалить все зависимости, связанные с Vue CLI.

// package.json
"@vue/cli-plugin-babel": "~4.5.0", // удаляем
"@vue/cli-plugin-eslint": "~4.5.0", // удаляем
"@vue/cli-plugin-router": "~4.5.0", // удаляем
"@vue/cli-plugin-vuex": "~4.5.0", // удаляем
"@vue/cli-service": "~4.5.0", // удаляем

Если вы используете на проекте SASS/SCSS, также можно удалить sass-loader, так как Vite из коробки поддерживает современные препроцессоры.

// package.json
"sass-loader": "^8.0.2" // удаляем

Ну и конечно же нам нужно добавить в зависимости сам Vite.

// package.json
"@vitejs/plugin-vue": "^1.6.1",
"vite": "^2.5.4",

И так как у нас проект на Vue 2 нам нужно добавить плагин для её поддержки. Для Vue 3 этого, конечно, делать не нужно.

// package.json
"vite-plugin-vue2" : "1.9.0" // поддержка Vue 2

Осталось только удалить vue-template-compiler. Его работу будет выполнять установленный ранее @vitejs/plugin-vue.

// package.json
"vue-template-compiler": "^2.6.11" // удаляем

Шаг #2: Поддерживаем только современные браузеры

Раз уж мы решили использовать самые передовые инструменты разработки, то было бы логично оставить за бортом устаревшие браузеры и не поддерживать их. Так мы получим максимально компактную и быструю сборку.

Т.е. это означает, что мы можем убрать из проекта Babel, так как современные браузеры имеют практически полную поддержку ES6. Если по каким-то причинам вам все же нужно поддерживать устаревшие браузеры, то у Vite есть для этого специальный плагин.

Для избавления от Babel мы первым делом удалим файл babel.config.js.

Далее остается ещё удалить некоторые зависимости из package.json.

// package.json
"babel-eslint": "^10.1.0", // удаляем
"core-js": "^3.6.5", // удаляем

Так как мы удалили babel-eslint, нужно немного поправить файл .eslintrc.

// .eslintrc
// удаляем
parserOptions: {
	parser: "babel-eslint",
},

Также нужно изменить настройку env.

// .eslintrc
env: {
	node: true, // удаляем
	es2021: true,
}

Ну и естественно для поддержки es2021 нужно обновить сам  eslint и  eslint-plugin-vue.

$ npm install eslint@8 eslint-plugin-vue@8

Шаг #3: Пишем конфиг Vite

Пришло время добавить конфигурационный файл для Vite. Для этого в корне проекта создадим файл vite.config.js. Вот так он выглядит в проекте, созданном с помощью команды npm init vite@latest

// vite.config.js

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()]
})

Для нашего проекта нужно добавить пару вещей. Во-первых, нам нужна поддержка второй версии Vue

// vite.config.js
import vue from '@vitejs/plugin-vue' // удаляем
import { createVuePlugin as vue } from "vite-plugin-vue2";

//...

В случае с Vue 3 это, конечно, не нужно.

И давайте ещё добавим поддержку импортов через @, как это сделано во Vue CLI. Согласитесь, так удобней, чем писать пути руками.

// vite.config.js
//...
const path = require("path");
export default defineConfig({
 //...
 resolve: {
   alias: {
     "@": path.resolve(__dirname, "./src"),
   },
 },
});

Шаг #4: Перемещаем index.html

В проектах, созданных через Vue CLI файл index.html находится в папке public. Vite работает иначе и у него index.html должен находится в корне проекта. Так что перемещаем index.html в корень. Также нужно немного поправить и содержание. Так как теперь у нас нет webpack, нам нужно удалить <%= htmlWebpackPlugin.options.title %> и <%= BASE_URL %>. Название сайта придётся вбивать ручками.

// index.html

<!--удаляем-->
<title><%= htmlWebpackPlugin.options.title %></title> 
<!--добавляем-->
<title>Hard Coded Title</title>

//...
<!--удаляем-->
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
<!--добавляем-->
<strong>We're sorry but this app doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>

Ну и пути все тоже прдётся прописать вручную.

// index.html

<!--удаляем-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!--добавляем-->
<link rel="icon" href="/favicon.ico">

И последнее, что нужно тут поменять, это добавление скрипта. Он теперь не инжектится автоматически, его тоже нужно прописать руками. с

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

Шаг #5: Обновляем скрипты в package.json

Вернёмся на секунду к package.json. Нам же нужно изменить команды. Они ведь по прежнему настроены на vue-cli-service.

// package.json
"serve": "vue-cli-service serve", // удаляем
"build": "vue-cli-service build", // удаляем
"dev": "vite",
"build": "vite build",
"serve": "vite preview",
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"

Шаг #6: Обновляем переменные окружения

Здесь у Vite всё очень похоже на Vue CLI. Например, названия файлов могут остаться такими же.

.env                # загружается всегда
.env.local          # загружается всегда, игнорируется гитом
.env.[mode]         # загружается только в указанном режиме
.env.[mode].local   # загружается только в указанном режиме, игнорируется гитом

А вот использование в Vite выглядит немного иначе. Доступ к переменным окружения там происходит не через переменную process, а через import.meta.env.

// router/index.js
base: process.env.BASE_URL, // удаляем
base: import.meta.env.BASE_URL,

Также меняется и логика наименования переменных окружения. Если при использовании Vue CLI их имена должны были начинаться с VUE_APP_, то при использовании Vite имена должны ожидаемо начинаться с VITE_.

Шаг #7: Добавляем расширение .vue при импорте компонентов

Как-то так.

// Home.vue
import HelloWorld from "@/components/HelloWorld.vue"; // .vue обязательно нужно указать

Если ваш проект уже очень большой и перспектива добавлять расширение ко всем импортам компонентов вызывает ужас, то можно обойтись и без этого. Нужно в vite.config.js добавить vue в список resolve.extensions.

// vite.config.js
//...
export default defineConfig({
  plugins: [vue()],
  resolve: {
    extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue'],
    //...
  },
});

Но документация Vite настоятельно рекомендует так не делать.

Шаг #8: Убираем волшебные комментарии

И последний шаг. Удаляем комментарии для динамического импорта. Эти комментарии предназначены для webpack, а мы его больше не используем.

// router/index.js
import(
    /* webpackChunkName: "about" */  // удаляем
    "../views/About.vue"
),

Vite сам автоматически проименует чанки на основе имен файлов, добавив к ним хэш. Типа такого: About.37a9fa9f.js.

Шаг #9: Наслаждаемся быстрым и приятным процессом разработки

Всего 8 шагов нам понадобилось, чтобы перевести приложение с Vue CLI на Vite. Можно смело набирать в консоли npm run dev и наслаждаться. Идите уже напишите какое-нибудь крутое приложение.