Как оптимизировать размер бандла Angular при использовании Font Awesome

Tags: Angular

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 и импортировать их только в те места, где они вам нужны.

Автор: Юрий Катков

No Comments

Add a Comment