Как оптимизировать размер бандла Angular при использовании Font Awesome
TL; DR: addIconPacks - это плохо. Это будет стоить вам на 1 Мб больше места (сжато). addIcons - это хорошо.
Angular Font Awesome
Всем нравится библиотека иконок Font Awesome: иконки очень красиво сделаны, их сайт прост и крут. Короче говоря, мы убедили нашего менеджера проекта купить пакет и начали использовать его повсюду. Мы предпочитаем SVG-иконки, потому что они поддерживаются повсюду и их довольно легко составлять, что позволяет создавать еще больше иконок. Мы используем Angular в качестве фреймворка, поэтому, естественно, у нас есть официальная библиотека angular-fontawome.
Библиотека добавляет компонент fa-icon и позволяет использовать значки следующим образом:
<fa-icon [icon]="['fas', 'coffee']" size="xs"></fa-icon>
Мы подумали: «Ну, давайте добавим и начнем его использовать, возможно, он позаботится о встряхивании дерева и тому подобном». Итак, мы создали модуль иконок и импортировали пакеты иконок следующим образом:
export class IconsModule { |
|
constructor(library: FaIconLibrary) { |
|
library.addIconPacks(far); |
|
library.addIconPacks(fas); |
|
library.addIconPacks(fasPro); |
|
} |
|
} |
Проблема
Обычно я проверяю размер бандла каждый раз, когда добавляю новую библиотеку в проект, а также каждые пару недель. Для этого я использую веб-пакет Bundle Analyzer, который является отличным инструментом, который визуализирует размер всех ваших модулей. Я запускаю это так:
npm run i18n && ng build --base-href / --aot --prod --stats-json |
К моему изумлению, когда я посмотрел статистику, я увидел, что Font Awesome занимает огромный кусок бандла!
Вам не нужно быть Дональдом Кнутом, чтобы понять, что icons.module.ts может использовать некоторые оптимизации. 1.9 Мб распаковано - это слишком много для 60 или около того иконок SVG, которые мы используем в проекте.
Решение
Короче говоря, addIconsPack не очень хорошо справляется с встряхиванием дерева. Так что, если вы не собираетесь использовать тысячи различных иконок в вашем проекте, вам нужно стереть его. Существует два основных подхода к импорту значков.
Неявный подход
При неявном подходе вы удалите FaIconLibrary.addIconsPack в файле модуля и затем перечислите значки, которые вы используете с помощью функции FaIconLibrary.addIcons, например:
import { faBalanceScale } from '@fortawesome/pro-solid-svg-icons'; |
|
import { faBan } from '@fortawesome/pro-regular-svg-icons'; |
|
export class IconsModule { |
|
constructor(library: FaIconLibrary) { |
|
library.addIcons( |
|
faBalanceScale, |
|
faBan, |
|
//... and the rest of icons) |
|
} |
|
} |
Обратите внимание, как я импортирую значки из пакетов: импортируйте {faBalanceScale} из '@ fortawesome/pro-solid-svg-icons' вместо импорта {faBalanceScale} из '@ fortawesome/pro-solid-svg-icons/faBalanceScale'. Оба способа абсолютно законны, и оба совершенно потрясающие. Первый способ намного проще для чтения, он не зависит от реализации и требует гораздо меньше символов для ввода, поэтому мы будем придерживаться его.
При таком подходе вы можете продолжать использовать свои значки, как и раньше, используя строковые константы, такие как <fa-icon [icon] = »[‘ fas ’,‘ coffee ’]» size = »xs»> </ fa-icon>. Обратите внимание, что если вы забыли добавить определенный значок в модуль, никто не сообщит вам о вашей ошибке во время компиляции. Ошибка появится в консоли во время выполнения, и все увидят пустое место вместо вашей красивой иконки.
Поэтому убедитесь, что вы всегда смотрите на результаты и тестируете свой код. Вот разница в размере бандла, когда мы применяем эту оптимизацию (все размеры в Мб). Обратите внимание, что столбец Stats имеет необработанный размер до того, как произошла конкатенация, минификация и встряхивание дерева. Анализируется размер после объединения, минификации и встряхивания дерева. Gzipped - это конечный результат, сжатый алгоритмом gzip. Наш размер бандла теперь в два раза меньше - неплохо только для одной оптимизации.
Явный подход
Явный подход требует, чтобы вы прекратили использовать строковые константы для имен значков в пользу переменных значков, которые вы будете импортировать в свои компоненты. Поэтому [icon] = ”[‘ fas ’,‘ coffee ’] станет [icon] =" faCoffee "в вашем шаблоне, и вы создадите новое поле faCoffee в классе компонентов.
Явный подход следует духу TypeScript и позволяет вашей IDE быстро видеть все фрагменты кода, где используется определенный значок, не полагаясь на поиск в свободном тексте. Также теперь все ошибки будут сообщаться во время компиляции, при условии, что вы всегда используете явный подход.
Недостатком является то, что у вас будет много кода в каждом компоненте, использующем значки, что приведет к немного большему размеру бандла и просто не будет приятным для просмотра.
Вот результаты, которые я получил после применения явного подхода к нашему проекту, где мы используем около 70 различных значков (размеры указаны в Мб).
Анализ
Я попытался продемонстрировать, что метод IconLibrary.addIconsPack не должен использоваться, потому что это приводит к увеличению размера бандла. Чтобы бороться с этим, вы должны импортировать иконки по отдельности, для чего мы видели два основных подхода.
Как вы могли видеть, неявный подход привел к лучшему сжатию. В зависимости от вашего проекта, вы можете предпочесть явный подход, особенно если у вас большой проект и набор значков постоянно меняется.
Дальнейшая оптимизация: для действительно больших приложений вы можете создать несколько ленивых модулей Icons и импортировать их только в те места, где они вам нужны.
Автор: Юрий Катков