FortAwesome / Font-Awesome

The iconic SVG, font, and CSS toolkit
https://fontawesome.com
Other
73.51k stars 12.2k forks source link

Tree shaking with Webpack 5 #18020

Open anteburazer opened 3 years ago

anteburazer commented 3 years ago

Describe the bug I have a simple React app with a custom Webpack setup but the three shaking doesn't work - https://github.com/anteburazer/tree-shaking-test

To Reproduce

git clone https://github.com/anteburazer/tree-shaking-test
yarn
yarn build
webpack --json > stats.json

Drag/drop stats.json on this site: https://chrisbateman.github.io/webpack-visualizer/

Expected behavior Only faGoogleDrive icon is included

Screenshots image

Version and implementation webpack 5.39.1 webpack-cli 4.7.2

Bug report checklist

Rybadour commented 2 years ago

I'm having the same issue. The root cause seems to be that for some reason these svg-icons packages has the following in their package.json:

"sideEffects": [
  "./index.js",
  "./index.es.js",
  "./styles.css"
],

Which means that any import on that "index.js" file is importing everything. Such as:

import { faCamera, faCheck } from '@fortawesome/free-solid-svg-icons';

To fix this I had to change to:

import { faCamera } from '@fortawesome/free-solid-svg-icons/faCamera';
import { faCheck } from '@fortawesome/free-solid-svg-icons/faCheck';
tagliala commented 2 years ago

The root cause seems to be that for some reason these svg-icons packages has the following in their package.json:

Reason: #18654

I will double check, but I've checked earlier today and I do not have three-shaking issues with 6.1.0 and a shakapacker pipeline based on webpack 5

tagliala commented 2 years ago

Hi @Rybadour,

I've just updated a test application here: https://github.com/diowa/ruby3-rails6-bootstrap-heroku

The asset pipeline is based on webpack 5. I can confirm tree shaking working in production

Relevant lines:

https://github.com/diowa/ruby3-rails6-bootstrap-heroku/blob/b980d1ebaa1a15afde6709672266b9312d815e1c/app/javascript/src/fontawesome.js#L3-L5

Production file:

image

Since there are a lot of ways of using webpack, if you can provide a reproducible test case showing the issue we will take a look. Even better if it is working with an older version of FA and breaking with a new one

Docs: https://fontawesome.com/docs/apis/javascript/tree-shaking

extempl commented 1 year ago

Same for me, I have like 24MB in --mode=production (26 in non-production ๐Ÿค”) of -svg-icons packages which imports index.mjs files. -svg-icons : 6.4.0 webpack: 5.81.0

ryanewtaylor commented 1 month ago

I have reproduced this issue as well, you can find the sample repo here: https://github.com/ryanewtaylor/repro-fontawesome-tree-shaking.

This does not allow for tree shaking

import { faEnvelope, faGolfBall } from "@fortawesome/free-solid-svg-icons";

image

While this does

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

image

It's a small workaround when you use just a handful of fonts but I don't understand why tree shaking is not working in the first example. Have I configured this incorrectly or is it an issue with font awesome or another dependency?

Dependencies are: โ”œโ”€โ”€ @fortawesome/fontawesome-svg-core@6.6.0 โ”œโ”€โ”€ @fortawesome/free-brands-svg-icons@6.6.0 โ”œโ”€โ”€ @fortawesome/free-regular-svg-icons@6.6.0 โ”œโ”€โ”€ @fortawesome/free-solid-svg-icons@6.6.0 โ”œโ”€โ”€ @fortawesome/react-fontawesome@0.2.2 โ”œโ”€โ”€ @types/react-dom@18.3.0 โ”œโ”€โ”€ @types/react@18.3.3 โ”œโ”€โ”€ html-webpack-plugin@5.6.0 โ”œโ”€โ”€ react-dom@18.3.1 โ”œโ”€โ”€ react@18.3.1 โ”œโ”€โ”€ ts-loader@9.5.1 โ”œโ”€โ”€ typescript@5.5.4 โ”œโ”€โ”€ webpack-bundle-analyzer@4.10.2 โ”œโ”€โ”€ webpack-cli@5.1.4 โ”œโ”€โ”€ webpack-dev-server@5.0.4 โ””โ”€โ”€ webpack@5.93.0

robmadole commented 1 month ago

@ryanewtaylor normally webpack doesn't tree-shake unless you are doing a production build. Have you given that a try?

ryanewtaylor commented 4 days ago

@robmadole, yes. The repo linked above (also here) reproduces the issue and is a production build.

robmadole commented 17 hours ago

@ryanewtaylor can you check the actual files that are generated?

# webpack --mode production && ls -h dist/main.js
asset index.html 382 bytes [emitted]
asset main.js 160 KiB [emitted] [minimized] (name: main) 1 related asset
runtime modules 1.2 KiB 5 modules
orphan modules 572 KiB [orphan] 3 modules
code generated modules 708 KiB [code generated]
  modules by path ./node_modules/ 134 KiB
    modules by path ./node_modules/prop-types/ 2.6 KiB 3 modules
    modules by path ./node_modules/react/ 6.7 KiB 2 modules
    modules by path ./node_modules/scheduler/ 5.12 KiB 2 modules
    modules by path ./node_modules/react-dom/ 117 KiB 2 modules
    ./node_modules/object-assign/index.js 2.06 KiB [built] [code generated]
  modules by path ./src/*.js 574 KiB
    ./src/index.js 378 bytes [built] [code generated]
    ./src/App.js + 3 modules 574 KiB [built] [code generated]
webpack 5.94.0 compiled successfully in 1508 ms
-rw-r--r--  1 robmadole  staff   160K Sep 13 15:50 dist/main.js
๎ฎ™ robmadole on ๏ป ~/Development/workbench/ephemeral/tree-shaking-test ๏ˆ ๎‚ master
# webpack --mode development && ls -h dist/main.js
asset index.html 441 bytes [emitted]
asset main.js 1.55 MiB [emitted] (name: main)
runtime modules 1.47 KiB 6 modules
modules by path ./node_modules/ 1.5 MiB
  modules by path ./node_modules/prop-types/ 27 KiB 5 modules
  modules by path ./node_modules/scheduler/ 32.4 KiB 4 modules
  modules by path ./node_modules/@fortawesome/ 572 KiB 3 modules
  modules by path ./node_modules/react/ 59.4 KiB 2 modules
  modules by path ./node_modules/react-is/ 7.01 KiB 2 modules
  modules by path ./node_modules/react-dom/ 840 KiB 2 modules
  ./node_modules/object-assign/index.js 2.06 KiB [built] [code generated]
modules by path ./src/*.js 1.95 KiB
  ./src/index.js 378 bytes [built] [code generated]
  ./src/App.js 1.58 KiB [built] [code generated]
webpack 5.94.0 compiled successfully in 673 ms
-rw-r--r--  1 robmadole  staff   1.5M Sep 13 15:50 dist/main.js

If I use --mode production it looks like tree-shaking kicks in. I don't know why the stats.json file doesn't reflect this. It's been a bit since I've used Webpack for much and I don't remember the nuances of that plugin.

Is this just a case of the stats plugin not reflecting tree-shaking results?