Обновил Webstartpage.ru

В последнее время много работы, никак не связанной с Vesp, зато очень хорошо оплачиваемой.
Чтобы не потерять навыки, решил поиграться с Nuxt 3 в свободное время на реальной задаче - переписал весь фронтенд своей домашней странички webstartpage.ru.
Это мой самый первый проект, живой до сих пор. Там можно авторизоваться через соцсети и хранить свои ссылки. Понятно дело, что в 2023 году такие странички не особо востребованы, потому что они уже встроены в браузер - но я привык к своей. Она была сделана и на MODX Evolutuion, и на Revolution (2 раза), потом на Vesp с Nuxt 2, а теперь вот и на Nuxt 3.
Получается, что этот сайт у меня всегда на острие прогресса!
Что изменилось в этот раз:
  • Vue 2 -> Vue 3
  • Nuxt 2 -> Nuxt 3
  • Vuex -> Pinia
  • Bootstrap 4 -> Bootstrap 5
Бэкенд на PHP остался без изменений.

Про Vue 3

Основное изменение, превнесённое 3й версией - Composition API. Это новый синтаксис, который вместо возврата объекта с data, methods, computed и т.д., вызывает всякие функции и переменные в одном месте.
Например у нас вот такой шаблон:
<template>
    <div>Variable: {{ count }}</div>
    <button @click="iterate">{{ text }}</button>
</template
А в Vue 2 такой код для его работы:
<script>
export default {
    data() {
        return {
            text: 'Iterate variable',
            count: 0,
        }
    },
    methods: {
        iterate() {
            this.count++
        },
    }
}
</script>
В Vue 3 будет вот так:
<script setup>
import {ref} from 'vue'

const text = ref('Iterate variable!')
const count = ref(0)

function iterate() {
    count.value++
}
</script>
Теперь переменные и функции не завязаны на контекст приложения, здесь просто нет this. Соответственно, их проще выносить в отдельные файлы и использовать в разных компонентах, оптимизируя логику работы.
На простых примерах разница может быть неочевидна, но в реальном приложении работать гораздо удобнее, да и кода писать меньше.
Конечно, Vue 3 поддерживает и старый Options API, но какой тогда смысл перехода на новую версию?
Также 3я версия нативно поддерживает TypeScript, который раньше я обходил стороной. Оказалось, что штука эта весьма полезна и позволяет серьёзно сократить количество возможных ошибок за счёт проверки типов переменных.

Про Nuxt 3

В этом же русле двигается и Nuxt 3 - всё на TypeScript, плюс автоматическая подготовка и загрузка типов, чтобы их не нужно было импортировать самостоятельно.
Полезные функции, вынесенные в директорию composables, загружаются самостоятельно. Например, работа с API у меня выглядит вот так:
<template>
    <div>
        <div v-show="!pending">Данные: {{ data }}</div>
        <button @click="refresh">Обновить данные</button>
    </div>
</template>
<script setup>
const {data, pending, refresh} = await useGet('end/point')
</script>
То есть: и данные, и статус загрузки и метод для перезагрузки - все возвращаются одной функцией, которая доступна в любом месте приложения.
Функция useGet - моя собственная composable, которая внутри себя использует родной useFetch с добавлением обработки ошибок и заголовков для авторизации. Есть еще usePost, usePatch, useDelete и useApi для специальных запросов с ручным указанием дополнительных параметров.
В итоге очень быстро привыкаешь вместо this.$axios.get писать useGet и не думать, а есть ли у тебя в этом месте вообще this? Потому что composables есть везде.
Помимо всяких автозагрузок и прикольных новых методов у Nuxt теперь и новый сервер для сборки Vite, и свой серверный движок Nitro.
Разработка стала просто молниеносной, до сих пор удивляюсь скорости обновления.

Про Pinia

К сожалению, не все модули Nuxt были обновлены для работы с новой версией, и больше всего мне не хватило Nuxt Auth. Так что авторизацию и работу с пользователем пришлось написать самостоятельно, используя Pinia.
Это современная замена хранилища Vuex, более простая и вся на TypeScript. Поэтому с ней можно прописать себе типы для работы, чтобы везде были подсказки.
Например, я указал своих юзеров:
export type VespUser = {
  id: number
  username: string
  fullname: string
  email: string
  scope: [string]
  [key: string]: any
}
export type RefVespUser = Ref & {
  value: VespUser | null
}
Добавил composable функцию useAuth для быстрого доступа к этому хранилищу, и стало хорошо:
С одной стороны, пришлось это всё писать самостоятельно. А с другой, я разобрался как оно работает и сторонние плагины мне больше не нужны.
Может пока что-то делаю неоптимально, потому что книга по TypeScript еще не дочитана, но оно работает и отлично помогает в разработке. В любом случае, подобные знания очень пригодятся при обновлении vesp-frontend до новых мажорных версий.

Про Bootstrap 5

Тут всё не так радужно, увы. Сам-то Bootstrap 5 в порядке, а вот Bootstrap-Vue пока что новую версию совсем не поддерживает. Ему прикрутили какой-то плагин для поддержки Vue 3, но вот именно CSS новой версии - нет.
Хорошо, что уже появлися новый проект, который они взяли под свое крыло - Bootstrap-Vue-Next. Это по сути ремейк оригинальной библиотеки, но на Vue 3 + TypeScript, и с 5й версией Bootstrap.
Он еще очень сырой и для серьёзной работы не готов. Многие модули по-прежнему используют родной Javascript от Bootstrap, который не работает при серверном рендере, например компонент Modal.
Мне серверный рендер не нужен, с мелкими багами я готов мириться - так что взял его для работы.
Интересно, что он из коробки поддерживает Nuxt 3, но пока что с ошибками. Через встроенный модуль у меня не заработал Dropdown - просто не реагировал на нажатия.
Пришлось отказаться от родного модуля и загружать компоненты вручную:
import {BDropdown} from 'bootstrap-vue-next'
Тогда работает без проблем.

Заключение

Новые версии Vue и Nuxt просто глоток свежего воздуха! Разработка стала гораздо быстрее, итоговая сборка в 2 раза меньше.
Слева на картинке сайт на Nuxt 2 грузит 2.14 Mb (515 Kb сжатых Gzip), а новый Nuxt 3 собрал всё в 854 Kb (246 Kb сжатых).
Все скрипты и стили помещаются в 246 килобайт! Функционал при этом тот же самый, ничего не убрано.
Единственное, что меня останавливает пока использовать этот стек везде - состояние Bootstrap-Vue-Next, он еще очень сырой. Для себя использовать можно, на заказ - рановато. На сервере не работает вообще, только на клиенте.
Если кому интересно сравнить новую и старую версии - я открыл доступ в репозиторий для всех желающих https://gitlab.com/bezumkin/webstartpage/
Вот здесь 2 ветки: Nuxt 2 и Master (Nuxt 3), можно склонировать и сравнивать было-стало. Там же есть конфигурация Docker, так что сложностей возникнуть не должно.
Если есть вопросы - задавайте в комментариях.

6 комментариев

Если кому то нужен отдельно Dropdown на nuxt3 рабочий вариант еще есть floating-vue
Василий Наумкин
Так он и в Bootstrap-Vue-Next рабочий, просто нужно импортировать вручную, а не через подключение модуля для Nuxt.
А зачем на этой странице вообще Bootstrap нужен? Для скорости разработки?
Василий Наумкин
Для удобства, конечно. Не самому же мне все стили для форм и модалок писать.
Для этого же я и Nuxt использую, хотя мог бы всё на чистом Vue3 + Vite сделать, но зачем?
Думается, если выпилить бутстрап, то размер стилей радикально сократится )) И страница будет ещё компактней Не обязательно самому всё писать - есть замечательный tailwind. Он умеет кстати собирать только то, что используется. Хотя и новый бутстрап, может, тоже уже так умеет - давно на него не глядел...
Василий Наумкин
Радикально - это насколько, еще на 50 килобайт из 250? А писанины это насколько увеличит?
Сейчас я просто использую готовые компоненты Bootstrap-Vue-Next вместе со стилями, а на замечательном Tailwind таких компонентов нет, нужно всё писать руками.
Я пробовал работать с Tailwind, мне не понравилось.
bezumkin.ru
Personal website of Vasily Naumkin
Прямой эфир
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так. А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен. Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500 Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи. ...
Futuris
04.04.2024, 08:56:12
Я просто немного запутался. Когда в абзаце "Vesp/Core" ты пишешь про "новый trait FileModel", я поду...
Василий Наумкин
20.03.2024, 21:21:52
Volledig!
Андрей
14.03.2024, 13:47:10
Василий! Как всегда очень круто! Моё почтение!
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо! Извини, тупанул.
Василий Наумкин
22.01.2024, 07:43:20
Давай-давай!
Василий Наумкин
24.12.2023, 14:26:13
Спасибо!