Skip to content

Latest commit

 

History

History
300 lines (217 loc) · 9.33 KB

README.md

File metadata and controls

300 lines (217 loc) · 9.33 KB

fontawesome-autoimport npm

Automatically detect and import fontawesome icons used in your webapp 🚀

This package aims to be framework (like React or Vue.js) agnostic. However, I have only tested it using webpack/VueJS.
👍 Feel free to open a PR with example/documentation for other use case!

How it works

It implements simple parsing techniques that would generate a file that imports all used icons without having to manage them every single time:

  • parse your package.json file to detect which font awesome styles are available in your project
  • parse any .vue and .js files in your src folder naively looking for fontawesome icon definitions (must by an array with explicit prefix)
  • generate the "import" file in src/plugins/fontawesome-autoimport.js (only if needed - aka icon added/removed in project 😎)

The parsing could be made manually or automatically, depending of your needs.

Installation

Yarn

$ yarn add -D @onedrynugget/fontawesome-autoimport

NPM

$ npm install --save-dev @onedrynugget/fontawesome-autoimport

Requirements

  • Make sure your source code exists within the src folder of the project's main directory.
  • Make sure you have installed appropriated fontawesome official plugin (vue-fontawesome, react-fontawesome...)

Setting up

Vue.js

Add these definitions to your entry point such as your main.js file

// Import autogenerated fontawesome imports
import "@/plugins/fontawesome-autoimport.js";

// Import regular fontawesome component
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
Vue.component("FontAwesomeIcon", FontAwesomeIcon);

React

Add these definitions to your entry point such as your index.js file

// Import autogenerated fontawesome imports
import "./plugins/fontawesome-autoimport.js";

Usage

Vue.js

The usage is almost identical to how you would normally use the official plugin except that you can't use the Shorthand that assumes a prefix of "fas", such as:

<font-awesome-icon icon="video" />

instead, you would just have to write the following:

<font-awesome-icon :icon="['fas', 'video']" />

React

The usage is almost identical to how you would normally use the official plugin except that you can't use the Shorthand that assumes a prefix of "fas", such as:

<FontAwesomeIcon icon="video" />
<FontAwesomeIcon icon={faVideo} />

instead, you would just have to write the following:

<FontAwesomeIcon icon={["fas", "video"]} />

Generating icon imports

There's basically two ways to do this, either manually or automatically.

Note: This tool will prioritize the pro versions of the installed svg icons set, so if for instance you have both free-solid-svg-icons and pro-solid-svg-icons, then the tool will use the pro one, otherwise the free one.

Manually

Executing the following npm command would run the script:

$ npm explore @onedrynugget/fontawesome-autoimport -- npm run gen

And you should see the success output message such as:

- Fontawesome treeshaking list generated. (took 10 ms)

Automatically upon build-time

This is achieved by hooking into webpack's events, so an additonal library is required, in our case, we'll be using before-build-webpack

$ npm install --save-dev before-build-webpack

Vue.js

Configure webpack (via vue.config.js or alternative) like this:

var WebpackBeforeBuildPlugin = require('before-build-webpack');
// ...
  module: {
    plugins: [
        new WebpackBeforeBuildPlugin(function(stats, callback) {
            const {execSync} = require('child_process');
            console.log(execSync('npm explore @onedrynugget/fontawesome-autoimport -- npm run gen').toString());
            callback();
        }, ['run', 'watchRun'])
    ]
  },
// ...

then build the project as you normally would:

$ yarn build

or

$ npm run build

The output of build should include the following line

- Fontawesome treeshaking list generated. (took 10 ms)

React

When using "create react app" scripts, the webpack config is handled by react-scripts. And so we can't directly update it except by using the "eject" provided command. However most dev don't want to take care of webpack config manually. Fortunatly, there is Craco 😍

Once Craco is installed in your webapp, add the following in craco.config.js:

var WebpackBeforeBuildPlugin = require("before-build-webpack");

module.exports = {
  webpack: {
    plugins: {
      add: [
        new WebpackBeforeBuildPlugin(
          function(stats, callback) {
            const { execSync } = require("child_process");
            console.log(
              execSync(
                "npm explore @onedrynugget/fontawesome-autoimport -- npm run gen"
              ).toString()
            );
            callback();
          },
          ["run", "watchRun"]
        )
      ]
    }
  }
};

then build the project as you normally would:

$ yarn build

or

$ npm run build

The output of build should include the following line

- Fontawesome treeshaking list generated. (took 10 ms)

Result

Once the script has finished executing, it should produce a file at src/plugins/fontawesome-autoimport.js which its content would look like the following:

// Generated by fontawesome-autoimport

// fas
import {
  faCircle as fasCircle,
  faAngleDown as fasAngleDown,
  faBars as fasBars
} from "@fortawesome/pro-solid-svg-icons";

// far
import {
  faSignOutAlt as farSignOutAlt,
  faComments as farComments
} from "@fortawesome/pro-regular-svg-icons";

import { library } from "@fortawesome/fontawesome-svg-core";
library.add(fasCircle, fasAngleDown, farSignOutAlt, fasBars, farComments);

If you're confused, you can check the example projects above: Vue.js, React.

Customization

Sometimes you may want to customize the pattern used to match fontawesome icons in your projet. It may happens if you have written a wrapper around the regular vue-fontawesome provided component (aka FontAwesomeIcon).

Wrapper example (Fa.vue):

<template>
  <FontAwesomeIcon :icon="faIcon" v-bind="$attrs" v-on="$listeners" />
</template>

<script>
  export default {
    props: { icon: { type: String, required: true } },
    computed: {
      faIcon: ({ icon }) => {
        const [, style, name] = icon.match(/(fa[a-z])-([a-z-]+)/);
        return [style, name];
      }
    }
  };
</script>

In that situation, a fontawesome icon will looks like <fa icon="fas-check" /> (html) or const icon = 'fas-check' (js). To handle that custom syntaxe, you can pass a custom pattern as env variable like this:

pattern="['\"](fa[a-z])-([a-z-]+)['\"]" npm explore @onedrynugget/fontawesome-autoimport -- npm run gen

or (for the automated version):

var WebpackBeforeBuildPlugin = require('before-build-webpack');
// ...
  module: {
    plugins: [
        new WebpackBeforeBuildPlugin(function(stats, callback) {
            const {execSync} = require('child_process');
            console.log(execSync(
              'npm explore @onedrynugget/fontawesome-autoimport -- npm run gen',
              { env: { pattern: `['"](fa[a-z])-([a-z-]+)['"]` } }
            ).toString());
            callback();
        }, ['run', 'watchRun'])
    ]
  },
// ...

Project background

This project is eavily inspired by @GTANAdam vue-fontawesome-autogen. In fact, the initial release of this project was proposed in a pull request as a complete rewrite of vue-fontawesome-autogen. Unfortunatly @GTANAdam is deeply attached to a custom syntaxe and using the customization provided in this package means a "breaking change" which seems too complicated in his projects. After a lot of discussion, I finally decided to go ahead and publish my own project.

Key differences compare to vue-fontawesome-autogen

  • Require by far less change to be used in an existing projet (only have to explicit the usage of fas style)
  • Take care of icons defined in .js files (useful for generated list based on an array/object/whatever imported from a .js file)
  • Handle webpack watchRun mode
  • Should be compatible with any futur font awesome style (no hard-coded list anymore) 🤞
  • Hint the developer about unknown icon (probably caused by forgotten style installation)
  • About 50% faster (well, the original one is probably fast enough, but still 😉)
  • Less code (less bug :trollface:)