Font-awesome: Tree-Shaking broken on fontawesome-svg-core

Created on 30 Dec 2019  路  17Comments  路  Source: FortAwesome/Font-Awesome

Describe the bug
fontawesome-svg-core tree shaking does not work properly and instead imports all of the modules at once, leading to nearly 60kb in unused bloat on every pageload.

To Reproduce
Simply stand up a Vue application, then test before and after as described in my comment on this issue: https://github.com/FortAwesome/vue-fontawesome/issues/172

Even though my environment is Vue-based, I believe this is affecting anyone dependent on the fontawesome-svg-core library.

Expected behavior
I would like to only import the library module
import { library } from '@fortawesome/fontawesome-svg-core'
as detailed in the documentation found here:
https://github.com/FortAwesome/vue-fontawesome#tree-shaking-alternative

Screenshots
Screenshots are available on the other issue. https://github.com/FortAwesome/vue-fontawesome/issues/172

Version and implementation
Version:

        "@fortawesome/fontawesome-svg-core": "^1.2.26",
        "@fortawesome/free-brands-svg-icons": "^5.12.0",
        "@fortawesome/free-regular-svg-icons": "^5.12.0",
        "@fortawesome/free-solid-svg-icons": "^5.12.0",
        "@fortawesome/vue-fontawesome": "^0.1.7",
        "babel-plugin-dynamic-import-webpack": "^1.1.0",
        "babel-plugin-syntax-dynamic-import": "^6.18.0",
        "compression-webpack-plugin": "^2.0.0",
        "laravel-mix": "^4.0.7",
        "laravel-mix-merge-manifest": "^0.1.2",
        "sass": "^1.15.2",
        "sass-loader": "^7.1.0",
        "svgo": "^1.3.0",
        "uglify-js": "^3.7.2",
        "vue": "^2.5.17",
        "webpack-bundle-analyzer": "^3.6.0",
        "webpack-chunk-rename-plugin": "^1.0.3"

Browser and version: N/A

  • [ ] SVG with JS
  • [ ] Web Fonts with CSS
  • [ ] SVG Sprites
  • [ ] On the Desktop

Bug report checklist

  • [x] I have filled out as much of the above information as I can
  • [x] I have included a test case because my odds go _way_ up that the team can fix this when I do
  • [x] I have searched for existing issues and to the best of my knowledge this is not a duplicate

All 17 comments

And I will say that if for some reason I am missing something here, can we _please_ get some better documentation on the requirements to implement this?

@raymondtri do you have the same results with FA 5.11.2?

@tagliala The last version I tested this on was FA 5.9.0, and tree-shaking was still not working on that branch either. Specifically for the svg core portion.

@raymondtri you'll have to provide a reproducible test case (codesandbox, GitHub repo, something) because tree-shaking is very dependent on the tool and versions used. We can take a look at it after that. Based on your package file you are using a Laravel Mix version that is a year old. My first thought goes there.

Good catch, I just updated to ^5.0.0 but unfortunately it still didn't solve anything.

I'll work on a reproducible test case, but a Laravel 6.x base setup should work.

In the meantime for anyone else experiencing this issue, @tagliala I'm using the individual component pattern. I simply wrote a new Vue web component that mirrors the font-awesome-icon Vue component almost exactly, and uses the font-awesome-icon Vue component as the only contents of mine. This way I don't have to worry about loading the entire 90kb svg-core into my build and it is only loaded on pages where it is used, and even deferred there.

<template>
  <font-awesome-icon
    :border="border"
    :fixedWidth="fixedWidth"
    :flip="flip"
    :icon="icon"
    :mask="mask"
    :listItem="listItem"
    :pull="pull"
    :pulse="pulse"
    :rotation="rotation"
    :swapOpacity="swapOpacity"
    :size="size"
    :spin="spin"
    :transform="transform"
    :symbol="symbol"
    :title="title"
  ></font-awesome-icon>
</template>
<script>

import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { config, dom } from '@fortawesome/fontawesome-svg-core';

import { library } from "@fortawesome/fontawesome-svg-core";

import { faFire } from "@fortawesome/free-solid-svg-icons/faFire";

config.autoAddCss = false

export default {
  props: {
    border: {
      type: Boolean,
      default: false
    },
    fixedWidth: {
      type: Boolean,
      default: false
    },
    flip: {
      type: String,
      default: null,
      validator: (value) => ['horizontal', 'vertical', 'both'].indexOf(value) > -1
    },
    icon: {
      type: [Object, Array, String],
      required: true
    },
    mask: {
      type: [Object, Array, String],
      default: null
    },
    listItem: {
      type: Boolean,
      default: false
    },
    pull: {
      type: String,
      default: null,
      validator: (value) => ['right', 'left'].indexOf(value) > -1
    },
    pulse: {
      type: Boolean,
      default: false
    },
    rotation: {
      type: [String, Number],
      default: null,
      validator: (value) => [90, 180, 270].indexOf(parseInt(value, 10)) > -1
    },
    swapOpacity: {
      type: Boolean,
      default: false
    },
    size: {
      type: String,
      default: null,
      validator: (value) => ['lg', 'xs', 'sm', '1x', '2x', '3x', '4x', '5x', '6x', '7x', '8x', '9x', '10x'].indexOf(value) > -1
    },
    spin: {
      type: Boolean,
      default: false
    },
    transform: {
      type: [String, Object],
      default: null
    },
    symbol: {
      type: [Boolean, String],
      default: false
    },
    title: {
      type: String,
      default: null
    }
  },
  components: {
    FontAwesomeIcon
  },
  mounted () {
    const id = 'fa-styles';
    if (!document.getElementById(`${id}`)) {
      const faStyles = document.createElement('style')
      faStyles.setAttribute('id', id)
      faStyles.textContent = dom.css()
      document.head.appendChild(faStyles);
    }
  }
}
</script>

Having the same issue. Bundle size is huge.

Screen-Shot-2020-04-07-20-50-31

Using with Nuxt:

  [
    'nuxt-fontawesome',
    {
      imports: [
        {
          set: '@fortawesome/free-solid-svg-icons',
          icons: [
            'faLevelUpAlt',
            'faSearchMinus',
            'faSearchPlus',
            'faSearch',
            'faChevronRight',
            'faChevronDown',
            'faCompressArrowsAlt',
            'faExpandArrowsAlt'
          ]
        }
      ]
    }
  ],
    "@fortawesome/fontawesome-svg-core": "1.2.28",
    "@fortawesome/free-solid-svg-icons": "5.13.0",
    "@fortawesome/vue-fontawesome": "0.1.9",
    "nuxt-fontawesome": "0.4.0",

@moltar we've seen the bundle analyzer report larger sizes than what is actually outputted (is that a word?) Can you look at the actual file in the file system?

What I actually did was get rid of nuxt-fontawesome completely.

And I am using @fortawesome/vue-fontawesome component directly.

import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faSearchPlus, faSearchMinus, faSearch } from '@fortawesome/free-solid-svg-icons'

And then using these included icons as needed.

Bundle size went down to virtually zero now. Can't even find it in the report.

Hm. I'm facing a similar issue with https://cdnjs.dev (https://github.com/cdnjs/static-website). Only importing the component & icons where needed, but seeing a massive block for fortawesome in my vendors bundle :(

image

The largest part of this is the svg-core, which I'm not even using directly, though it seems to be used by the vue icon component. Really sucks that this is taking such a large part of my vendor bundle.

@MattIPv4 interesting. Give me a bit, I'm going to load up the static-website locally.

Apologies for the lack of info in the readme. npm run dev runs the site in dev mode locally. npm run dev:generate:noroutes will run the site generated on a local dev server. npm run dev:analyze will build the site with webpack analyzer (for the above bundle explorer).

Yep @MattIPv4 I took a look at npm run dev:analyze and the numbers look right. The SVG core has a lot of functionality built into it. Looks like you really aren't using advanced features (masking, transforming, etc) in the site. If that size is objectionable I'd recommend going directly with the SVGS. They can be accessed through the @fortawesome/fontawesome-free package.

Ah okay, makes sense. Thanks for taking a look! Will have a play with just using the SVGs :)

I'm having the same issue. I only import @fortawesome/fontawesome-svg-core for the library function and it shows up in my bundle size as over 45 KB.

import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { faBars, ...} from '@fortawesome/free-solid-svg-icons';

export const icons = [ faBars, ... ];

library.add(...icons);

export default function registerIcons(Vue) {
  Vue.component('FA', FontAwesomeIcon);
}

grafik

How would one go about using fontawesome without the fontawesome-svg-core package? I coudn't find any documentation on that.

If it helps, you can see how we're doing it in cdnjs/static-website:

We're importing the svg directly https://github.com/cdnjs/static-website/blob/master/components/corner.vue
Using the svg nuxt module, which returns the svg as a component https://github.com/cdnjs/static-website/blob/master/nuxt.config.js#L99

I ended up using https://github.com/Cweili/vue-fa instead of vue-fontawesome and fontawesome-svg-core. This saved me about 33k on the resulting bundle size. Quite a big chunk for freatures I never even used :)

I ended up using https://github.com/Cweili/vue-fa instead of vue-fontawesome and fontawesome-svg-core. This saved me about 33k on the resulting bundle size. Quite a big chunk for freatures I never even used :)

Thanks for this suggestion. vue-fa educed our bundle size significantly too.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

yarcowang picture yarcowang  路  3Comments

rufengch picture rufengch  路  3Comments

ghost picture ghost  路  3Comments

huuphat picture huuphat  路  3Comments

tdolph picture tdolph  路  3Comments