Релиз @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)
russelgalrussel gal
06.03.2024 21:40

https://unocss.dev/integrations/nuxt

https://icones.js.org/collection/all

204 345 иконок

и никаких проблем с "Hydration"

<i class="i-material-symbols-360"/>
bezumkinВасилий Наумкин
07.03.2024 05:11

Если бы я так решал все возникающие проблемы, то не написал бы ни одного дополнения или модуля.

А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал с 2013 года =)

С возвращением!

russelgalrussel gal
09.03.2024 20:17

А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал с 2013 года =)

лет 11 назад ушел от пхп и пр модх, прост

по наводке вашего фаната глянул этот пост

ну и решил, что альтернатива не помешает

тем более, что там не только fontawesome

bezumkin
Василий Наумкин
09.04.2024 04:45
Ошибка 500 Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи. Во...
futuris
Futuris
04.04.2024 08:56
Я просто немного запутался. Когда в абзаце &quot;Vesp/Core&quot; ты пишешь про &quot;новый trait Fil...
bezumkin
Василий Наумкин
20.03.2024 21:21
Volledig!
Андрей
14.03.2024 13:47
Василий! Как всегда очень круто! Моё почтение!
russelgal
russel gal
09.03.2024 20:17
А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал ...
inetlover
Александр Наумов
27.01.2024 03:06
Василий, спасибо! Извини, тупанул.
bezumkin
Василий Наумкин
22.01.2024 07:43
Давай-давай!
bezumkin
Василий Наумкин
24.12.2023 14:26
Спасибо!
bezumkin
Василий Наумкин
27.11.2023 05:43
Ура!
bezumkin
Василий Наумкин
25.11.2023 11:30
Vesp тянет 2 зависимости: vesp-frontent для фронта и vesp-core для бэкенда. Их можно обновлять, но э...