Font-awesome: Tree shaking not working with webpack 4 and 5.1 prerelease

Created on 2 Jun 2018  路  8Comments  路  Source: FortAwesome/Font-Awesome

For example, the simplest project is used:

package.json

{
  "name": "test-fortawesome",
  "version": "1.0.0",
  "main": "src/index.js",
  "scripts": {
    "build": "webpack --mode production"
  },
  "sideEffects": false,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.0-11",
    "@fortawesome/free-brands-svg-icons": "^5.1.0-8",
    "@fortawesome/free-regular-svg-icons": "^5.1.0-8",
    "@fortawesome/free-solid-svg-icons": "^5.1.0-8"
  },
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.4",
    "babel-preset-env": "^1.7.0",
    "webpack": "^4.10.2",
    "webpack-cli": "^3.0.0"
  }
}

webpack.config.js

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: './bundle.js'
  },
  module: {
    rules: [{
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        use: {
          loader: 'babel-loader',
          options: {
            presets: 'env'
          }
        }
      },
    ]
  }
};

If I use this method of loading icons (after npm run build), the file size is equal to 35.1 KiB.

index.js

import { library, dom } from '@fortawesome/fontawesome-svg-core'

import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch'
import { faFileArchive } from '@fortawesome/free-solid-svg-icons/faFileArchive'
import { faDownload } from '@fortawesome/free-solid-svg-icons/faDownload'
import { faGithub } from '@fortawesome/free-brands-svg-icons/faGithub'

library.add(
  faSearch,
  faFileArchive,
  faDownload,
  faGithub
)

dom.watch()

But if I use the following method of loading icons, the file size is 792 KiB.

index.js

import { library, dom } from '@fortawesome/fontawesome-svg-core'

import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { faFileArchive } from '@fortawesome/free-solid-svg-icons'
import { faDownload } from '@fortawesome/free-solid-svg-icons'
import { faGithub } from '@fortawesome/free-brands-svg-icons'

library.add(
  faSearch,
  faFileArchive,
  faDownload,
  faGithub
)

dom.watch()

How to turn on the tree shaking?

waiting for feedback

Most helpful comment

Tree shaking in FA 5.1 does work with Webpack 4. Here's a repo to demonstrate.

Unfortunately, there are a few ways to get the configuration right and many ways to mis-configure.

I think in this case, it may not be working because of the babel-loader rule in the webpack.config.js. My demo repo, I did not include that intentionally, and it works.

In fact, if I had not used a webpack.config.js at all, and just let Webpack 4 do its defaults, it would also have worked if not for this performance regression. Until the fix for that bug finds its way into the minifier plugin that Webpack 4 depends upon (uglify-es aka terser), you may need to modify webpack.config.js to either disable the collapse_vars compression option, or use Babel Minify instead of the Webpack UglifyJS plugin. I have a draft of these documented work arounds ready to publish to our docs on fontawesome.com but they have yet to be published.

All 8 comments

Hi!

Thanks for being part of the Font Awesome Community.

I can confirm.

The bundle file with the second approach (which is also the suggested approach)

@mlwilkerson could you please take a look?

This is definitely not working with the latest fontawesome version (that includes the pre-release ones).

Tree shaking in FA 5.1 does work with Webpack 4. Here's a repo to demonstrate.

Unfortunately, there are a few ways to get the configuration right and many ways to mis-configure.

I think in this case, it may not be working because of the babel-loader rule in the webpack.config.js. My demo repo, I did not include that intentionally, and it works.

In fact, if I had not used a webpack.config.js at all, and just let Webpack 4 do its defaults, it would also have worked if not for this performance regression. Until the fix for that bug finds its way into the minifier plugin that Webpack 4 depends upon (uglify-es aka terser), you may need to modify webpack.config.js to either disable the collapse_vars compression option, or use Babel Minify instead of the Webpack UglifyJS plugin. I have a draft of these documented work arounds ready to publish to our docs on fontawesome.com but they have yet to be published.

Yes babel-loader is not allowing to tree shake fontawesome, is there any way around it?

I am using babel-loader and react fontawesome. Babel helps to transpile react JSX.

@mlwilkerson Thanks! You have suggested a way to solve the problem with babel-loader. If you use the beta version of the library babel-loader 8.0.0-beta.3 and configure it correctly, tree shaking with the library will work.

package.json

{
  "name": "test-fortawesome",
  "version": "1.0.0",
  "main": "src/index.js",
  "scripts": {
    "build": "webpack --mode production"
  },
  "sideEffects": false,
  "dependencies": {
    "@fortawesome/fontawesome-svg-core": "^1.2.0",
    "@fortawesome/free-brands-svg-icons": "^5.1.0",
    "@fortawesome/free-regular-svg-icons": "^5.1.0",
    "@fortawesome/free-solid-svg-icons": "^5.1.0"
  },
  "devDependencies": {
    "@babel/core": "^7.0.0-beta.51",
    "@babel/plugin-proposal-class-properties": "^7.0.0-beta.51",
    "@babel/preset-env": "^7.0.0-beta.51",
    "babel-loader": "^8.0.0-beta.3",
    "webpack": "^4.12.0",
    "webpack-cli": "^3.0.8"
  }
}

webpack.config.js (slowly)

const path = require('path');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: './bundle.js'
  },
  module: {
    rules: [{
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { modules: false }],
            ],
            plugins: ['@babel/plugin-proposal-class-properties'],
          }
        }
      },
    ]
  }
};

index.js

import { library, dom } from '@fortawesome/fontawesome-svg-core'

import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { faFileArchive } from '@fortawesome/free-solid-svg-icons'
import { faDownload } from '@fortawesome/free-solid-svg-icons'
import { faGithub } from '@fortawesome/free-brands-svg-icons'

library.add(
  faSearch,
  faFileArchive,
  faDownload,
  faGithub
)

dom.watch()

And now the bundle file.js weighs only 34 KB.

Update. Yes, without configuring UglifyWebpackPlugin build works very slowly. By the way mlwilkerson is much faster.

webpack.config.js

const path = require('path');
const UglifyWebpackPlugin = require('uglifyjs-webpack-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    filename: './bundle.js'
  },
  module: {
    rules: [{
        test: /\.js$/,
        include: path.resolve(__dirname, 'src'),
        use: {
          loader: 'babel-loader',
          options: {
            presets: [
              ['@babel/preset-env', { modules: false }],
            ],
            plugins: ['@babel/plugin-proposal-class-properties'],
          }
        }
      },
    ]
  },
  optimization: {
    minimizer: [
      new UglifyWebpackPlugin({
        uglifyOptions: {
          compress: {
            collapse_vars: false
          }
        }
      })
    ]
  }
};

Why isn't it working with @babel/preset-react? Any idea?

What's broken? My version with beta version of babel-loader does not work?

if you use babel6.x,you have to set modules false , it's work;
babel 7.x set modules false default

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Eschwinm picture Eschwinm  路  3Comments

yarcowang picture yarcowang  路  3Comments

rufengch picture rufengch  路  3Comments

AndersDK12 picture AndersDK12  路  3Comments

tdolph picture tdolph  路  3Comments