How to trim the FontAwesome JS for your website, using Emacs Lisp.
This post briefly goes through the FontAwesome 5 setup, the problem statement and a solution for that.
I signed up for the FontAwesome 5 Pro Kickstarter, and I have to say that this is one of my few Kickstarter fundings that delivered really well!
Thank you FontAwesome!
FontAwesome 5 Setup #
FontAwesome 5 supports an awesome new way of loading icons, using
SVG with JS. The benefit is that you simply load one
fontawesome-all.js file and everything just works!.
<head> <!--load everything--> <script defer src="/static/fontawesome/fontawesome-all.js"></script> </head> <body> <!--icon--> <i class="fas fa-user"></i> </body>
With FontAwesome 5 Pro, I get about 2700 icons packed in that
fontawesome-all.js. While that is great, there are 2 issues:
- I don’t need all of those 2700 icons on my site. That file is roughly 1.7 MB (minified or not) which I need not unnecessarily load for all my visitors.
- Anyone can easily pirate the whole JS file and use it for free!
The solution is simple — I just comment out all the lines with SVG code for the icons that I don’t use.
But searching for the icons I need in all the icon packs (Solid, Regular, Light, Brand) in that single 5k+ line JS file is not fun, especially when I want to add/remove icons occasionally.
fontawesome-choose was born!
- I list the icons I need in
M-x fontawesome-choosein the
The code is in the next section, but you can also find the latest version in my repo.
Note that while I have used this on Fontawesome 5 Pro, it should work just as well on Fontawesome 5 Free too.
;; Helper function `fontawesome-choose' used to uncomment only the ;; icons the user cares about in `fontawesome-all.js'. (defconst fontawesome-choose-icons '("list-alt" ;categories "tags" "rss" "link" "heart" ;like "reply" "retweet" "github" ;"github-alt" "github-square" "twitter" ;"twitter-square" "gitlab") "List of icons to choose from fontawesome-all.js. Used in `fontawesome-choose'.") (defun fontawesome-choose () "Comment out all icons in fontawesome-all.js except the selected few. Minifying the resultant .js will then remove the commented icons, thus drastically reducing the minified JS size. Set the `fontawesome-choose-icons' variable to the list of icons that you want to keep uncommented." (interactive) (let ((case-fold-search nil) (count 0)) (save-excursion (goto-char (point-min)) (while (re-search-forward "^var icons" nil :noerror) (let ((begin (progn (forward-line 1) (point))) end) (re-search-forward "^\\};") (forward-line 0) (backward-char 1) (setq end (point)) ;; First comment all the lines (save-excursion (narrow-to-region begin end) (goto-char (point-min)) (while (re-search-forward "^\\s-*\\(\"\\)" nil :noerror) (replace-match "// \\1" nil nil nil 1)) (widen)) ;; Now uncomment only the selected icons (save-excursion (narrow-to-region begin end) (goto-char (point-min)) (let* ((icon-regexp (regexp-opt fontawesome-choose-icons 'symbols)) (regexp (format "^\\s-*\\(//\\s-*\\)\"%s\":" icon-regexp))) (while (re-search-forward regexp nil :noerror) (replace-match "" nil nil nil 1) (setq count (1+ count)))) (widen)))) (message "fontawesome-choose: Uncommented %d icons matching %S" count fontawesome-choose-icons))))
This solution solves the first problem wonderfully — After
fontawesome-all.js is just 71 KB (down from 1.7
That’s a 25x factor reduction! The minification step is important
because that removes all the commented lines from the JS. I do the
The second problem, that of piracy, is difficult to solve completely using this. But whoever pirates this reduced FontAwesome from my site won’t get the real deal 😎.
Emacs-Lisp saves the day once again!