vue-fontawesome icon indicating copy to clipboard operation
vue-fontawesome copied to clipboard

Tree-shaking vs import

Open stebogit opened this issue 4 years ago • 15 comments

Hello, in the many examples I saw online on how to import the icons to reduce the dimensions of the build I found a lot of repetition:

import {faCircle, faBookOpen, faDollarSign, faDesktop} from "@fortawesome/pro-solid-svg-icons";
library.add(
  faCircle, faBookOpen, faDollarSign, faDesktop,
);

Would the following work the same, with the tree-shake doing its thing?

import * as fas from "@fortawesome/pro-solid-svg-icons";
library.add(
  fas.faCircle,
  fas.faBookOpen,
  fas.faDollarSign,
  fas.faDesktop,
);

stebogit avatar Mar 14 '21 05:03 stebogit

What you are doing in the 2nd code is not tree shaking, you are importing all the icons Try to build it and compare their bundle size.

christhofer avatar Mar 19 '21 02:03 christhofer

Thanks @christhofer, I suspected so. Then though I don't understand the usefulness of the library. From the docs it seems to me it's suggested the library allows you to reduce the final bundle size

Explicitly selecting icons offer the advantage of only bundling the icons that you use in your final bundled file. This allows us to subset Font Awesome's thousands of icons to just the small number that are normally used.

Do you have some more insight on what the library does and how it helps to keep the bundle small?

stebogit avatar Mar 19 '21 05:03 stebogit

import {faCircle, faBookOpen, faDollarSign, faDesktop} from "@fortawesome/pro-solid-svg-icons";

By doing this, only 4 icons are imported, so the final bundle only contains 4 icons you need instead of all font awesome icons. You will have them in the bundle even if you are not adding them to library.add()

Regarding library.add(), I'm also not really sure how it works. It is for vue-fontawesome component to process :icon=['fas', 'coffee'] props and output the correct svg.

christhofer avatar Mar 19 '21 07:03 christhofer

I would suggest to use explicit usage, this way you are 100% sure you only bundle what you use

<template>
  <FontAwesomeIcon :icon="$options.icons.faEye" />
</template>

<script>
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
import { faEye } from '@fortawesome/pro-regular-svg-icons/faEye'

export default {
  components: { FontAwesomeIcon },
  icons: { faEye },
  // ...
}
</script>

ps: we killed 4mb of bundle size just by using explicit icon imports

unrevised6419 avatar May 24 '21 09:05 unrevised6419

I get index.es.js?ad3d:295 Could not find one or more icon(s) {prefix: "fas", iconName: "user"} {} although the icon is show...

adrianwix avatar Aug 18 '21 17:08 adrianwix

@iamandrewluca I did your approach and a huge improvement on size.

Why is there no documentation on this vs every example they provide has them using this approach:

import { faEye } from '@fortawesome/pro-regular-svg-icons/'

vs

import { faEye } from '@fortawesome/pro-regular-svg-icons/faEye'

The first approach drops in that huge index file, etc.

brianrwells avatar Aug 26 '21 13:08 brianrwells

@brianrwells It's because most modern tools (webpack, rollup, esbuild) can handle tree-shaking import { faEye } from '@fortawesome/pro-regular-svg-icons. We offer the alternative for folks who are having issues with the tooling (using older versions, misconfiguration, etc.)

robmadole avatar Aug 26 '21 20:08 robmadole

@robmadole So its a pretty recent Vue project, we followed FontAwesome's examples for install ... in fact I just made sure I am using the last version of Webpack. What if any misconfig issue would cause the tree shaking to not occur?

brianrwells avatar Aug 26 '21 21:08 brianrwells

@brianrwells did you run a production build?

robmadole avatar Aug 26 '21 21:08 robmadole

@robmadole

"scripts": { "stats": "STATS=server yarn build:prod", "build:prod": "yarn run version && vue-cli-service build --mode production", }

yarn run stats

gives us this Screen Shot 2021-08-26 at 5 10 33 PM

brianrwells avatar Aug 26 '21 21:08 brianrwells

Can you check the actual file size on disk too? We've seen problems with analyzer reporting larger than actual sizes.

robmadole avatar Aug 26 '21 21:08 robmadole

@robmadole with our fonts setup like this

`import { library, dom } from "@fortawesome/fontawesome-svg-core" import { faMapMarker, faConciergeBell, faNewspaper, faEllipsisH, faPhone, faVideo, faTimesCircle, faShareAlt, faExternalLinkAlt, faChevronRight, faChevronDown, faChevronLeft, faCog, faSnowflake, faExclamationTriangle, faTv, faQuestionCircle, faLayerGroup, faSwimmingPool, faBars, faLink, faTimes, } from "@fortawesome/free-solid-svg-icons" import { faTwitter, faYoutube, faAppStoreIos, faGooglePlay, faYelp, } from "@fortawesome/free-brands-svg-icons" import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome" import { faBooks, faFileChartPie, faTint, faHouse, faIdCardAlt, faDumpster, faTrash, faGavel, faExternalLink, faExternalLinkSquare, } from "@fortawesome/pro-regular-svg-icons"

import { faBrowser, faInfoCircle, faBuilding, faBoxBallot, faMapMarkerAlt, } from "@fortawesome/pro-duotone-svg-icons" import { faHurricane, faLocationCircle } from "@fortawesome/pro-solid-svg-icons" import VueMasonry from "vue-masonry-css"

library.add( customIcons.vbLogo, faMapMarker, faConciergeBell, faNewspaper, faEllipsisH, faPhone, faVideo, faTimesCircle, faShareAlt, faExternalLinkAlt, faTwitter, faChevronRight, faChevronDown, faYoutube, faChevronLeft, faCog, faBooks, faFileChartPie, faTint, faHouse, faIdCardAlt, faDumpster, faTrash, faGavel, faSwimmingPool, faSnowflake, faExclamationTriangle, faTv, faQuestionCircle, faLayerGroup, faAppStoreIos, faGooglePlay, faBrowser, faInfoCircle, faBars, faBuilding, faLink, faBoxBallot, faExternalLink, faExternalLinkSquare, faTimes, faHurricane, faYelp, faMapMarkerAlt, faLocationCircle`

gives us this

Screen Shot 2021-08-26 at 5 37 20 PM

brianrwells avatar Aug 26 '21 21:08 brianrwells

So I'm assuming it landed in chunk-vendors. You'll have to inspect that file and see if it's including more icons than you need. Another way to test is to remove half the icons that you're using and see if the size is reduced. If the file shrinks when you do this that means tree-shaking is working.

robmadole avatar Aug 26 '21 21:08 robmadole

@robmadole Its not tree shaking, in chunk map file, faBowlingPins is there which it should not be

brianrwells avatar Aug 26 '21 21:08 brianrwells

@robmadole

doing it this way

`import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome" import { library, dom } from "@fortawesome/fontawesome-svg-core"

//free-solid-svg-icons import { faNewspaper } from "@fortawesome/free-solid-svg-icons/faNewspaper" import { faPhone } from "@fortawesome/free-solid-svg-icons/faPhone" import { faVideo } from "@fortawesome/free-solid-svg-icons/faVideo" import { faTimesCircle } from "@fortawesome/free-solid-svg-icons/faTimesCircle" import { faShareAlt } from "@fortawesome/free-solid-svg-icons/faShareAlt" import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons/faExternalLinkAlt" import { faChevronRight } from "@fortawesome/free-solid-svg-icons/faChevronRight" import { faChevronDown } from "@fortawesome/free-solid-svg-icons/faChevronDown" import { faChevronLeft } from "@fortawesome/free-solid-svg-icons/faChevronLeft" import { faCog } from "@fortawesome/free-solid-svg-icons/faCog" import { faSnowflake } from "@fortawesome/free-solid-svg-icons/faSnowflake" import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons/faExclamationTriangle" import { faTv } from "@fortawesome/free-solid-svg-icons/faTv" import { faQuestionCircle } from "@fortawesome/free-solid-svg-icons/faQuestionCircle" import { faLayerGroup } from "@fortawesome/free-solid-svg-icons/faLayerGroup" import { faSwimmingPool } from "@fortawesome/free-solid-svg-icons/faSwimmingPool" import { faBars } from "@fortawesome/free-solid-svg-icons/faBars" import { faLink } from "@fortawesome/free-solid-svg-icons/faLink" import { faTimes } from "@fortawesome/free-solid-svg-icons/faTimes"

//free-brands-svg-icons import { faTwitter } from "@fortawesome/free-brands-svg-icons/faTwitter" import { faYoutube } from "@fortawesome/free-brands-svg-icons/faYoutube" import { faAppStoreIos } from "@fortawesome/free-brands-svg-icons/faAppStoreIos" import { faGooglePlay } from "@fortawesome/free-brands-svg-icons/faGooglePlay" import { faYelp } from "@fortawesome/free-brands-svg-icons/faYelp"

//free-brands-svg-icons import { faBooks } from "@fortawesome/pro-regular-svg-icons/faBooks" import { faFileChartPie } from "@fortawesome/pro-regular-svg-icons/faFileChartPie" import { faTint } from "@fortawesome/pro-regular-svg-icons/faTint" import { faHouse } from "@fortawesome/pro-regular-svg-icons/faHouse" import { faIdCardAlt } from "@fortawesome/pro-regular-svg-icons/faIdCardAlt" import { faDumpster } from "@fortawesome/pro-regular-svg-icons/faDumpster" import { faTrash } from "@fortawesome/pro-regular-svg-icons/faTrash" import { faGavel } from "@fortawesome/pro-regular-svg-icons/faGavel" import { faExternalLink } from "@fortawesome/pro-regular-svg-icons/faExternalLink" import { faExternalLinkSquare } from "@fortawesome/pro-regular-svg-icons/faExternalLinkSquare"

//pro-duotone-svg-icons import { faMapMarkerAlt } from "@fortawesome/pro-duotone-svg-icons/faMapMarkerAlt" import { faBrowser } from "@fortawesome/pro-duotone-svg-icons/faBrowser" import { faInfoCircle } from "@fortawesome/pro-duotone-svg-icons/faInfoCircle" import { faBuilding } from "@fortawesome/pro-duotone-svg-icons/faBuilding" import { faBoxBallot } from "@fortawesome/pro-duotone-svg-icons/faBoxBallot"

//pro-solid-svg-icons import { faHurricane } from "@fortawesome/pro-solid-svg-icons/faHurricane" import { faLocationCircle } from "@fortawesome/pro-solid-svg-icons/faLocationCircle"`

give us this:

Screen Shot 2021-08-26 at 6 00 30 PM

brianrwells avatar Aug 26 '21 22:08 brianrwells