Много людей работают на Vue 2 и опасаются по разным причинам переходить на Vue 3. Многие думают попробовать Vue впервые, и не знают с какой версии начать. В этой статье мы попробуем рассказать как просто начать работать с VueJS 3 и Composition API.
Еще один вопрос , который часто вызывает беспокойство - стоит ли заодно начать использовать TypeScript? Или это усложнит задачу освоения Vue 3?
А почему Vue?
Для тех опытных программистов, которые только хотят заняться фронтендом, для новичков, для опытных фронтэндеров из других фреймворков это главный вопрос. На этот вопрос отвечает ключевое слово - реактивность. Реактивность - это глоток свежего воздуха, революционная концепция сделавшая работу веб разработчика по настоящему удобной. А Vue - реактивный фреймворк. Но почему именно Vue, ведь есть еще Angular и React? А потому, что Vue вышел последним, с учетом все ошибок и достижений Ангулара и Реакта. Понятно, что если вы идете в проект уже написанный, например, на Реакте, то вам нужен Реакт. В случае же если вы начинаете новый проект лучшим выбором является Vue. Он шустрый, он оптимально написан, он легко изучается, он гармоничен наконец. Раньше, до версии Vue 3, Реакт мог бы поспорить с Vue в плане технологичности, но с выходом Composition API и новой концепции реактивности во Vue 3 это перестало иметь место.
Готов ли Vue 3 для использования в работающих проектах?
Ответ - да. Не обязательно ждать официального объявления о выходе окончательного релиза. Текущая, на момент написания, версия 3.1.5, ведет себя стабильно и отлично работает у многих людей в уже запущенных проектах.
Но есть но - не все сопутствующие инструменты разработчика уже готовы, и не все сторонние библиотеки и плагины уже поддерживают Composition API и TypeScript.
Хорошо то, что Vue Devtools Plugin для Хрома для третьей версии Vue уже есть и вполне рабочий, хотя может быть команда Vue еще будет его допиливать.
Нужен ли TypeScript?
Ответ - да. Как реактивность когда-то стала лучшим помощником веб разработчика, так и TS стал лучшим (конечно есть альтернативы) помощником программиста на JavaScript. TypeScript делает ваш код более стабильным, предсказуемым и качественным. Некоторые даже утверждают, что использование TypeScript позволяет сократить количество тестов, или даже делает их не нужными. Да, чтобы перейти на TypeScript, надо будет затратить определенные усилия, но это окупится. Некоторые утверждают, что применение TypeScript залог здорового и спокойного сна. Я с этим согласен.
Как начать?
Замечательный инструмент Vue CLI решает все проблемы.
Процесс установки Vue 3 и TypeScript
После установки Vue CLI командой
npm install -g @vue/cli
# OR
yarn global add @vue/cli
запускаете
vue create habr
тут habr - название нашего проекта. Каталог с таким именем будет создан в текущем каталоге. И туда будет помещены все нужные каталоги и файлы.
? Please pick a preset: Manually select features
нам нужно в ручную выбирать конфигурацию
? Check the features needed for your project:
◉ Choose Vue version
◉ Babel
◉ TypeScript
◯ Progressive Web App (PWA) Support
◉ Router
◯ Vuex
◉ CSS Pre-processors
◉ Linter / Formatter
◯ Unit Testing
◯ E2E Testing
тут важно указать - Choose Vue version, чтобы выбрать Vue 3, по умолчанию установится Vue 2
Babel - нужен - писать нам надо на ECMAScript 2015+
ну конечно указать TypeScript,
PWA - если не знаете, то и не ставим. Без него вполне можно жить.
Router - нужен, если это большое приложение, а не один компонент.
Vuex - уже не нужен, подробнее ниже.
CSS Pre-processors - если используете включайте, рекомендую. Чистый CSS не для слабонервных.
Linter / Formatter - а вот без этого нельзя, ставим. Чтобы потом код форматировался сам, и ошибки детектировались автоматом.
Unit Testing / E2E Testing - для простоты не ставим, можно доставить позже.
Дальше проще, CLI предлагает, а мы выбираем:
? Check the features needed for your project: Choose Vue version, Babel, TS, Router, CSS Pre-processors, Linter
? Choose a version of Vue.js that you want to start the project with 3.x
это понятно, мы же хотим VueJS 3
? Use class-style component syntax? No
не используем class-style component syntax!
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? Yes
? Use history mode for router? (Requires proper server setup for index fallback in production) Yes
да, после можно поменять
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): Sass/SCSS (with dart-sass)
ВАЖНО не ставьте node-sass - он depreciated, выбирайте - dart-sass!
? Pick a linter / formatter config: Prettier
Prettier - отличная вещь, привыкнете, скажете спасибо
? Pick additional lint features: Lint on save
удобно форматировать код после сохранения, так как мы будем использовать встроенный сервер, который тоже перерисовывает интерфейс после сохранения.
? Where do you prefer placing config for Babel, ESLint, etc.? In dedicated config files
в будущем так удобнее для смены конфигурации
? Save this as a preset for future projects? Yes
можете сохранить настройки, для будущих экспериментов, рекомендую.
После недолгой установки мы должны увидеть такую информацию:
Vue CLI v4.5.13
Creating project in /Users/admin/Documents/WORK/habr.
Initializing git repository...
Installing CLI plugins. This might take a while...
added 1335 packages in 2m
Invoking generators...
Installing additional dependencies...
added 127 packages, and changed 1 package in 25s
Running completion hooks...
Generating README.md...
Successfully created project habr.
Get started with the following commands:
$ cd habr
$ npm run serve
Далее переходим в каталог проекта, и запускаем npm run serve (встроеный Dev сервер).
В браузере по адресу http://localhost:8080/ - мы увидим пустой проект с логотипом Vue, это то, что нам и нужно.
Встроенный Dev сервер Vue очень удобен для работы, так как все изменения в вашем коде он отображает на лету. А вот при публикации, мы будем копировать наши готовые скрипты уже на реальный сервер, ну это уже другая статья.
Если у вас новый проект, начинаем с нуля. А если у вас уже есть проект написанный на Vue2 - копируете компоненты в проект, может кое-где и кое- что надо будет поменять, но ваш проект написанный на чистом JS и на Vue 2 должен заработать и в данной конфигурации. Вы можете не менять старые компоненты, использующие Options API, они будут работать. Новые уже начинайте писать на Vue 3 и TypeScript.
Переход на Composition API
Это все очень просто, и на этот счет масса статей. Важно понять, что Composition API позволяет вывести часть логики в отдельные модули. Компоненты у вас не будут раздуваться, и легче будет следовать принципу - один компонент - одна функциональная обязанность. Код станет суше. А переход не сложен.
Если же вы начинаете Vue с нуля, то лучше даже и не писать на старом Options API, хотя знать его нужно, если хотите читать старый код.
Лучший источник информации https://v3.vuejs.org/guide/introduction.html. Vue славится своей понятной и ясной документацией, и затруднений быть не должно. Там же кстати есть и Гайд по миграции с версии 2 на 3.
Важная концепция - ref и reactive - описана в статье Vue 3 Composition API: Ref или Reactive. И есть еще масса статей. Это основа реактивности Vue, и то что делает его крутым.
Для изучения рекомендую сайт - https://vueuse.org изучая примеры с него можно многому научиться, тем более, что там уже много кода на ТС.
Недавно появился новый синтаксический сахар - <script setup>. Он уменьшает boilerplate, т.е. приходится писать меньше конструкций. Но новичкам, лучше пока не усложнять себе понимание и его не использовать, на мой взгляд. Я по крайней мере не спешу, мне без него кажется наглядней, да и там возникают свои сложности. В будущем можно и перейти.
А как же быть с запросами к бэкенду?
Это не сложно, если у вас уже есть запущенный сервер с бэкендом. Помните мы указывали, что будем хранить конфигурации в отдельных файлах (In dedicated config files). Вот такой отдельный файл - vue.config.js
vue.config.js
module.exports = {
pages: {
index: {
entry: 'src/main.ts',
template: 'public/index.html'
}
},
publicPath: '/',
configureWebpack: {
devtool: 'source-map'
},
devServer: {
proxy: {
'/api/*': {
target: 'http://myBackEnd.loc/',
changeOrigin: true
}
}
}
}
Раздел devServer/proxy как раз и нужен, чтобы описать куда обращаться за данными с бэкенда.
Таким образом мы видим веб страницу по адресу Dev сервера, а запросы шлем через прокси на сервер бэкенда.
Форматирование с поддержкой TS
Vue CLI уже создал для нас два файла:
.eslintrc.js
module.exports = {
root: true,
env: {
node: true
},
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020
},
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
'@typescript-eslint/no-this-alias': ['off']
},
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/prettier',
'@vue/typescript',
'@vue/typescript/recommended',
'@vue/prettier/@typescript-eslint'
]
}
Тут обратите внимание на правило - vue3-essential, eslint:recommended, typescript/recommended.
Теперь после того, как вы сохраняете файл, форматирование произойдет автоматически. А если все написано правильно ваше IDE порадует вас зеленой птичкой, означающей, что в файле нет ошибок.
Лично я стараюсь не отходить от рекомендованных настроек, и как можно меньше делать исключений, которые можно создавать и в этих файлах, и в файлах с кодом. Если разработчики Vue и TS рекомендуют, я им верю.
Теперь ваше IDE будет вам помогать писать на TypeScript.
Некоторые индивидуальные предпочтения можно записать в конфигурации prettier:
.prettierrc
{
"semi": false,
"singleQuote": true,
"trailingComma": "none",
"arrowParens": "avoid"
}
Мне удобней так, а вы решайте сами. Но главное, чтобы вся команда придерживалась одинаковых настроек.
А как же VUEX
А что касается Vuex, то он не нужен. Создаете свои модули, включаете их в нужные компоненты, как описано моей статье VueJS 3: Глобальное состояние с помощью Composition API. В этой статье я еще осторожно писал, что подход без Vuex возможен, сейчас я уже точно могу сказать, что он вполне проверен на практике и гораздо удобнее. Любые данные состояния приложения отлично хранятся в модулях.
Что же касается удобного отображения состояния в Vue Devtools Plugin, то конечно мы лишаемся некоторого удобства в плане работы с actions, но видеть состояние мы можем в информации о компоненте. Так что мы ни чего не теряем, ведь actions у нас и не будет.
TypeScript - это не страшно
Чтобы начать писать на ТС достаточно в тег скрипт компонентов включить lang=“ts”, вот так:
<script lang=“ts">
Дальше просто, пишете как обычно, на ECMAScript 2015+. Наш линтер и преттиер будут иногда сообщать об ошибках. Внимательно их читаем, потом читаем документацию ТС или советы со StackOverflow и модифицируем код, чтобы ошибок не было.
И еще, вам часто будут советовать поставить тип any. Никогда этого не делайте. Во первых применяя any, вы расписываетесь в собственной слабости, а во вторых теряете преимущества, которые дает ТС. По моему опыту довольно большого проекта, ни разу не пришлось использовать any, всегда находилось решение.
Иногда линтер и преттиер не ругаются, а браузер и Дев сервер могут ругаться , такие ошибки тоже внимательно изучаем. Это другой тип ошибок - ошибки компиляции ли транспиляции, не знаю точно. Постепенно вы поймете как их избегать.
А если вам нужно использовать код написанный на JS? Не проблема, используйте. Для этого в файле tsconfig.json надо указать "allowJs": true.
Если в компоненте интенсивно используется библиотека на JS, то в крайнем случае можно и сам компонент оставить на JS. Такой компонент будет без проблем работать в проекте, наряду с компонентами на TS.
Постепенно у вас появится набор своих, сложных типов, и вы их сможете собрать в отдельные файлы и каталоги. Обычно использование типа не сложно.
Объявляем:
export interface MyComplexType {
typeKey1: number
typeKey2: string
}
И применяем:
const myFunction = (arg: MyComplexType) => { …. }
но в случае со свойствами компонента, нужна будет такая конструкция
props: {
myComplexData: {
type: Object as PropType<MyComplexType>,
required: true
}
},
конечно вверху надо будет включить PropType:
import { defineComponent, PropType} from 'vue'
Еще очень важно понимать, что ТС не работает в runtime. Поэтому проверка типа несколько усложняется:
Например:
export const phonesRule = (phoneList: Array<string> | unknown): boolean => {
if (!Array.isArray(phoneList)) return false
const goodList = phoneList.filter(item => checkPhone(item))
return goodList.length === phoneList.length
}
мы не можем обратиться к аргументу функции без предварительной проверки, что он массив.
export const estateTypeIsZero = (estate: Estate | unknown): boolean => {
if (estate && typeof estate=== 'object') {
const estateType = (estate as Estate).type
if (estateType === 0) return false
}
return true
}
мы обязаны проверить, что аргумент - объект, а еще стоит проверить есть ли нужный ключ у объекта, но тут мы точно знаем, что если он объект, то такой ключ будет.
В обоих примерах аргумент либо нужного нам типа, либо unknown, так как это требование сторонней библиотеки, если бы не unknown проверка бы упростилась.
Еще важный аспект - можно находить уже готовые типы.
Например код метода:
const fileChanged = (e) => { ... }
вызовет ошибку, так как тип события e не определен. Вам надо либо самому создать такой тип, либо найти уже описанный. В моем случае, мне подошел тип EventData из используемой мной библиотеки xstate:
import { EventData } from 'xstate'
и
const fileChanged = (e: EventData) => { ... }
начал работать без ошибки.
Еще очень важная концепция - enum. Советую разобраться и применять.
В целом нужно не бояться ТС, вполне по силам любому разобраться. Но это интересно и полезно. Конечно все что тут изложено касательно TS изложено новичком в TypeScript, в прошлом году я его еще не знал, так что за неточности прошу прощения;
Пример рабочего стека
Ниже я приведу набор плагинов / библиотек, которые поддерживают Composition API, TypeScript и которые работают с Vue последней версии и которых использую я:
package.json
"dependencies": {
"@vuelidate/core": "^2.0.0-alpha.16",
"@vuelidate/validators": "^2.0.0-alpha.13",
"axios": "^0.21.1",
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-i18n": "^9.1.6",
"vue-router": "^4.0.8",
"xstate": "^4.19.1"
}
npm list
├── @typescript-eslint/eslint-plugin@4.29.0
├── @typescript-eslint/parser@4.29.0
├── @vue/cli-plugin-babel@4.5.13
├── @vue/cli-plugin-eslint@4.5.13
├── @vue/cli-plugin-typescript@4.5.13
├── @vue/cli-service@4.5.13
├── @vue/compiler-sfc@3.1.5
├── @vue/eslint-config-prettier@6.0.0
├── @vue/eslint-config-typescript@7.0.0
├── @vuelidate/core@2.0.0-alpha.22
├── @vuelidate/validators@2.0.0-alpha.19
├── axios@0.21.1
├── babel-eslint@10.1.0
├── core-js@3.16.0
├── eslint-plugin-prettier@3.4.0
├── eslint-plugin-vue@7.15.1
├── eslint@6.8.0
├── prettier@2.3.2
├── sass-loader@8.0.2
├── sass@1.37.5
├── typescript@4.1.6
├── vue-i18n@9.1.7
├── vue-router@4.0.10
├── vue@3.1.5
└── xstate@4.23.1
В целом мне хватает таких сторонних библиотек: axios, vue-i18n, vuelidate и xstate.
Ну с axios все понятно, обращение к серверу. Библиотека старая и проверенная, может и не на TS, но это не мешает ее использовать в проекте на TypeScript.
vue-i18n - это библиотека для локализации, а так как мы не в Англии, нам без нее никуда - https://github.com/intlify/vue-i18n-next
vuelidate - библиотека для валидация форм, навороченная, и концептуально правильно спроектированная - https://github.com/vuelidate/vuelidate
xstate - библиотека для работы с конечными автоматами. Если вы разберетесь как с ней работать, вы серьезно упростите свою работу - https://xstate.js.org. У меня есть статья на эту тему - Используем XSTATE для VueJS.
Все эти три библиотеки - vue-i18n, vuelidate и xstate поддерживают Composition API, и TypeScript. Их постоянно обновляют и дополняют. Их всех я очень активно использую, и могу заверить, что глюков в них почти нет, работают они надежно и сюрпризов не подкидывают.
А что касается CSS библиотек, то не могу их рекомендовать, так как обхожусь без них. Надеюсь найдется автор, который сможет сделать по ним статью.
На этом я закругляюсь, надеюсь, что эта информация поможет кому-нибудь.