2. Установка и Vite
Установка Vue 3 с Vite ⚡
Заголовок раздела «Установка Vue 3 с Vite ⚡»Vite — это не просто сборщик, это машина времени для разработки! Пока Webpack запускается 30 секунд и пересобирает весь проект, Vite стартует за 300ms и обновляет только изменённые модули. Секрет? Нативные ES-модули в браузере! 🚀
Создание проекта: npm create vue@latest ✨
Заголовок раздела «Создание проекта: npm create vue@latest ✨»Официальный способ создать Vue 3 проект — через create-vue, который использует Vite под капотом:
npm create vue@latest my-appТы увидишь интерактивный wizard:
✔ Project name: … my-app✔ Add TypeScript? … Yes ← обязательно!✔ Add JSX Support? … No✔ Add Vue Router for SPA? … Yes✔ Add Pinia for state management? … Yes✔ Add Vitest for Unit Testing? … Yes✔ Add an End-to-End Testing Solution? … No✔ Add ESLint for code quality? … Yes✔ Add Prettier for code formatting? … Yes✔ Add Vue DevTools 7 extension? … Yes
Scaffolding project in ./my-app...Done. ✔Затем:
cd my-appnpm installnpm run devОткрой http://localhost:5173 — проект живёт! 🎉
Структура проекта 🗂️
Заголовок раздела «Структура проекта 🗂️»my-app/├── public/ ← статичные файлы (favicon, robots.txt)│ └── favicon.ico│├── src/ ← весь исходный код здесь│ ├── assets/ ← изображения, шрифты, глобальные стили│ │ └── main.css│ ││ ├── components/ ← переиспользуемые компоненты│ │ ├── common/ ← общие: BaseButton, BaseInput, etc.│ │ └── features/ ← фичевые: UserCard, ProductList, etc.│ ││ ├── views/ ← страницы (роуты)│ │ ├── HomeView.vue│ │ ├── AboutView.vue│ │ └── UserView.vue│ ││ ├── router/ ← Vue Router конфигурация│ │ └── index.ts│ ││ ├── stores/ ← Pinia сторы│ │ ├── user.ts│ │ └── cart.ts│ ││ ├── composables/ ← переиспользуемая логика│ │ ├── useUser.ts│ │ └── useFetch.ts│ ││ ├── types/ ← TypeScript типы и интерфейсы│ │ └── index.ts│ ││ ├── utils/ ← вспомогательные функции│ │ └── formatDate.ts│ ││ ├── App.vue ← корневой компонент│ └── main.ts ← точка входа│├── index.html ← главный HTML (Vite точка входа)├── vite.config.ts ← конфигурация Vite├── tsconfig.json ← конфигурация TypeScript├── env.d.ts ← типы для .vue файлов└── package.jsonVite конфигурация 🔧
Заголовок раздела «Vite конфигурация 🔧»import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'import { fileURLToPath, URL } from 'node:url'
export default defineConfig({ plugins: [ vue(), // vueDevTools() — раскомментируй для Vue DevTools ],
resolve: { alias: { // @ → src/ (очень удобно!) '@': fileURLToPath(new URL('./src', import.meta.url)) } },
server: { port: 5173, // порт dev-сервера open: true, // автоматически открывать браузер proxy: { // проксирование API запросов '/api': { target: 'http://localhost:3000', changeOrigin: true } } },
build: { outDir: 'dist', // папка для production сборки minify: 'esbuild', // минификация (очень быстрая!) rollupOptions: { output: { // разделение кода на чанки manualChunks: { vendor: ['vue', 'vue-router', 'pinia'] } } } }})Алиасы — чистый импорт без ../../
Заголовок раздела «Алиасы — чистый импорт без ../../»// ❌ Без алиасов — ужасноimport UserCard from '../../../components/UserCard.vue'import { useUser } from '../../../composables/useUser'
// ✅ С алиасом @ → src/import UserCard from '@/components/UserCard.vue'import { useUser } from '@/composables/useUser'SFC — Single File Component анатомия 🧬
Заголовок раздела «SFC — Single File Component анатомия 🧬».vue файл — это всё в одном: шаблон, логика, стили:
<!-- 1️⃣ ШАБЛОН — HTML с Vue директивами --><template> <div class="user-card"> <img :src="user.avatar" :alt="user.name" /> <h2>{{ user.name }}</h2> <p>{{ user.email }}</p> <button @click="emit('follow', user.id)"> {{ isFollowing ? 'Отписаться' : 'Подписаться' }} </button> </div></template>
<!-- 2️⃣ СКРИПТ — TypeScript логика --><script setup lang="ts">import { computed } from 'vue'
// TypeScript интерфейсinterface User { id: number name: string email: string avatar: string}
// Определяем props с типамиconst props = defineProps<{ user: User following: number[]}>()
// Определяем eventsconst emit = defineEmits<{ follow: [userId: number]}>()
// Вычисляемое свойствоconst isFollowing = computed(() => props.following.includes(props.user.id))</script>
<!-- 3️⃣ СТИЛИ — CSS изолированный в компоненте --><style scoped>.user-card { border: 1px solid #e2e8f0; border-radius: 12px; padding: 16px; text-align: center;}
button { background: #42b883; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer;
/* :deep() пробивает scoped изоляцию в дочерних компонентах */ :deep(.child-class) { color: red; }}</style><script setup> vs setup() функция 📜
Заголовок раздела «<script setup> vs setup() функция 📜»Есть два способа писать Composition API:
<!-- Способ 1: <script setup> — рекомендуемый синтаксис Vue 3.2+ --><script setup lang="ts">import { ref } from 'vue'
const count = ref(0)// Всё объявленное здесь автоматически доступно в шаблоне!</script><!-- Способ 2: setup() функция — более явный, нужен для defineComponent --><script lang="ts">import { ref, defineComponent } from 'vue'
export default defineComponent({ name: 'MyComponent', setup() { const count = ref(0)
// Нужно явно возвращать всё, что нужно в шаблоне return { count } }})</script><script setup> — это синтаксический сахар. Компилятор Vue превращает его в setup() функцию автоматически. Преимущества:
- Меньше boilerplate
- Лучший вывод типов TypeScript
- Лучший runtime производительность (меньше замыканий)
Scoped стили — изоляция CSS 🎨
Заголовок раздела «Scoped стили — изоляция CSS 🎨»<template> <div class="card"> <p class="text">Текст в карточке</p> </div></template>
<style scoped>/* scoped: Vue добавляет уникальный атрибут к элементам: *//* <div class="card" data-v-7ba5bd90> *//* <p class="text" data-v-7ba5bd90> */
.card { /* Компилируется в: .card[data-v-7ba5bd90] */ background: white;}
/* :deep() — стилизация дочерних компонентов */:deep(.child-button) { /* .card[data-v-7ba5bd90] .child-button */ color: blue;}
/* :slotted() — стилизация содержимого слота */:slotted(p) { color: gray;}
/* :global() — глобальный стиль из scoped блока */:global(body) { margin: 0;}</style>CSS Modules — альтернатива scoped:
<template> <!-- $style.card — объект с уникальными классами --> <div :class="$style.card"> <p :class="$style.text">Текст</p> </div></template>
<style module>/* Компилируется в уникальный класс: .card_abc123 */.card { background: white; }.text { color: black; }</style>Глобальные стили и CSS переменные 🌍
Заголовок раздела «Глобальные стили и CSS переменные 🌍»/* src/assets/main.css — глобальные стили */:root { /* CSS переменные для темы */ --color-primary: #42b883; --color-dark: #35495e; --color-background: #ffffff; --color-text: #213547; --border-radius: 8px; --font-size-base: 16px;}
/* Тёмная тема */@media (prefers-color-scheme: dark) { :root { --color-background: #0f172a; --color-text: #e2e8f0; }}
* { box-sizing: border-box;}
body { margin: 0; font-family: Inter, system-ui, sans-serif; background: var(--color-background); color: var(--color-text);}// main.ts — подключаем глобальные стилиimport './assets/main.css'import { createApp } from 'vue'import App from './App.vue'
createApp(App).mount('#app')TypeScript настройка для Vue 3 🔷
Заголовок раздела «TypeScript настройка для Vue 3 🔷»{ "compilerOptions": { "target": "ES2020", "module": "ESNext", "lib": ["ES2020", "DOM", "DOM.Iterable"], "moduleResolution": "bundler", "strict": true, // строгий TypeScript "jsx": "preserve", "skipLibCheck": true, "paths": { "@/*": ["./src/*"] // алиасы для TypeScript } }, "include": ["src/**/*", "env.d.ts"], "exclude": ["node_modules", "dist"]}// env.d.ts — типы для .vue файлов/// <reference types="vite/client" />
declare module '*.vue' { import type { DefineComponent } from 'vue' const component: DefineComponent<{}, {}, any> export default component}Основные npm команды 🛠️
Заголовок раздела «Основные npm команды 🛠️»npm run dev # запуск dev-сервера (http://localhost:5173)
# Сборкаnpm run build # production сборка в dist/npm run preview # превью production сборки
# Тестыnpm run test:unit # запуск unit тестов (Vitest)npm run test:e2e # запуск e2e тестов (Playwright/Cypress)
# Линтингnpm run lint # проверка ESLintnpm run format # форматирование Prettier
# Типыnpx vue-tsc --check # проверка TypeScript типовVS Code окружение 💻
Заголовок раздела «VS Code окружение 💻»{ "recommendations": [ "Vue.volar", // Language Server (IntelliSense, автодополнение) "Vue.vscode-typescript-vue-plugin", // TypeScript в .vue файлах "esbenp.prettier-vscode", // форматирование "dbaeumer.vscode-eslint", // линтинг "bradlc.vscode-tailwindcss" // если используешь Tailwind ]}{ "editor.formatOnSave": true, "editor.defaultFormatter": "esbenp.prettier-vscode", "[vue]": { "editor.defaultFormatter": "Vue.volar" }, "typescript.tsdk": "node_modules/typescript/lib", "vue.inlayHints.missingProps": true}Резюме ⚡
Заголовок раздела «Резюме ⚡»Vite + Vue 3 — идеальная пара:
npm create vue@latest— один wizard создаёт полноценный проект- Структура
src/components,src/views,src/stores— стандартная и понятная - SFC (
.vue) — шаблон + скрипт + стили в одном файле <script setup>— рекомендуемый синтаксис, меньше кода, лучше типы<style scoped>— изоляция CSS без утечек
Следующий урок — Composition API! 🧩