Релиз @vesp/nuxt-fontawesome

Пока есть свободное время, решил попробовать себя в качестве разработчика модулей для Nuxt 3.
Понятное дело, что один модуль я уже написал - но это для Vesp, и большой популярности у него не будет. А вот подключение Font Awesome к текущей версии Nuxt всё еще является проблемой.
Официального модуля нет, есть только куча инструкций на разных сайтах, как это сделать своим плагином. Да вот беда, такой способ не работает с серверным рендером.
И вот я решил это исправить!

Проверяем официальный способ

Первым делом нужно диагностировать проблему. Идём на официальный сайт и читаем инструкцию.
Далее пробуем её применить:
npx nuxi@latest init fontawesome
cd ./fontawesome
npm i --save @fortawesome/vue-fontawesome @fortawesome/free-solid-svg-icons
Дальше создаём плагин в plugins/fontawesome.ts:
mkdir plugins
nano plugins/fontawesome.ts
В плагин вставляем код из инструкции для Nuxt 3. Он импортирует сразу все solid иконки, чего обычно делать не следует, но для теста сойдёт.
import { library, config } from '@fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { fas } from '@fortawesome/free-solid-svg-icons'

config.autoAddCss = false
library.add(fas)

export default defineNuxtPlugin(({vueApp}) => {
  vueApp.component('font-awesome-icon', FontAwesomeIcon, {})
})
Ну а стили добавляем в nuxt.config.ts:
export default defineNuxtConfig({
  devtools: { enabled: false },
  ssr: true,
  css: ['@fortawesome/fontawesome-svg-core/styles.css']
})
Осталось только отредактировать app.vue вот таким образом
<template>
  <div>
    <font-awesome-icon icon="user" />
  </div>
</template>
Теперь можно запустить проект через npm run dev и открыть http://localhost:3000.
И что мы видим в консоли? Внезапно, ошибку гидратации - хотя мы всё сделали по инструкции.
Если вы не знаете, что такое гидратация, и почему ошибок в неё лучше избегать, то вот цитата из документации Vue:
Vue проверяет соответствие виртуального дерева DOM, сгенерированного на стороне клиента, со структурой DOM, отрисованной на стороне сервера. Если будет выявлено расхождение, то гидратация будет прекращена, существующий DOM выброшен и отрисовка выполнится с нуля. В консоли браузера выведется предупреждение, но приложение будет работать.
Помимо ошибки браузера будет еще и запись в консоли:
И получается, что иконки FontAwesome работают только в браузере. Если заглянуть в исходник страницы, то вместо готового SVG будет заглушка <!---->:

В чём же дело?

Суть проблемы в том, что все рецепты подключения FontAwesome в Nuxt 3 полагаются на официальный vue-fontawesome, а он рендерит иконки через функции из своего ядра, используя методы DOM - и это работает только в браузере.
Авторы vue-fontawesome об этом знают, вопрос обсуждается в репозитории с 2022 года, но решения пока нет. Да и не думаю, что они будут сильно переписывать ядро ради поддержки SSR.
Мне же нужно было заставить работать серверный рендер для @vesp/frontend, так что я закопался в исходники, вытащил оттуда всю нужную логику по работе с иконками и засунул в свои кастомные компоненты.
А сейчас вот надумал всё это доработать и выложить отдельно, чтобы мой способ могли использовать не только юзеры Vesp.
Таким образом, @vesp/nuxt-fontawesome не использует vue-fontawesome, и поэтому работает серверный рендер.
Не буду грузить подробностями, но я постарался реализовать все имеющиеся параметры и настройки оригинальных компонентов. Насколько я вижу, получилось неплохо, процентов на 90 всё работает так же, но нужно еще тестировать.
Заодно узнал много нового, например о возможности объединения разных иконок с помощью маски или компонента слоёв.

Устанавливаем @vesp/nuxt-fontawesome

Возвращаемся к нашему проекту, удаляем плагин и меняем зависимости:
npm r --save @fortawesome/vue-fontawesome
npm i --save @vesp/nuxt-fontawesome
rm -rf ./plugins
Дальше редактируем nuxt.config.ts:
export default defineNuxtConfig({
  devtools: { enabled: false },
  ssr: true,
  modules: ['@vesp/nuxt-fontawesome'],
  fontawesome: {
    suffix: true,
    icons: {
      solid: ['faUser'],
    }
  }
})
Запускам проект через npm run dev и проверяем ошибочки.
А ошибок-то и нет!
В консоли появилась строка Fontawesome module is ready, а в исходнике страницы тег SVG:
Более того, теперь вы можете имортировать иконки не как faUser, faArrowRight , а как просто user, arrow-right в настройках модуля. Это очень удобно, учитывая, что именно под такими именами они и выводятся при поиске на официальном сайте. Там даже можно копировать название кликом =)

Заключение

Исходный код модуля в Github - https://github.com/bezumkin/nuxt-fontawesome
Там же инструкция по установке и настройке, расписаны все возможные параметры и даны примеры. В директории playground лежит подробный пример, на котором я проверяю работу компонентов.
@vesp/frontend тоже был обновлён и теперь подключает иконки через новый модуль. Пользователям Vesp и Орбиты никаких настроек делать не нужно, только обновить зависимости.
Если вам было интересно - распространите среди жильцов нашего ЖЭКа!

Обновлено 07.03.2024

Попытался добавить свою разработку в общий список модулей для Nuxt, и получил предложение его переименовать. Изначально было nuxt3-fontawesome, но, говорят, номер версии в названии использовать не нужно.
Поэтому стало @vesp/nuxt-fontawesome.
Если модуль будет пользоваться популярностью, есть шанс, что он станет официальным @nuxtjs/fontawesome.

Обновлено 14.03.2023

Модуль доступен на официальном сайте - https://nuxt.com/modules/nuxt-fontawesome

3 комментария

204 345 иконок
и никаких проблем с "Hydration"
<i class="i-material-symbols-360"/>
Василий Наумкин
Если бы я так решал все возникающие проблемы, то не написал бы ни одного дополнения или модуля.
А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал с 2013 года =)
С возвращением!
А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал с 2013 года =)
лет 11 назад ушел от пхп и пр модх, прост
по наводке вашего фаната глянул этот пост
ну и решил, что альтернатива не помешает
тем более, что там не только fontawesome
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
Спасибо!