'Can Font Awesome be used with importmaps in Rails 7?

I'm new to Rails 7's importmap and the documentation says you can pin a JavaScript module and then import it:

./bin/importmap pin react react-dom
import React from "react"
import ReactDOM from "react-dom"

How would that work with Font Awesome? Font Awesome's documentation says you should install the package:

npm install --save @fortawesome/fontawesome-free

but then, when it comes to using it, it says:

<script defer src="/your-path-to-fontawesome/js/brands.js"></script>
<script defer src="/your-path-to-fontawesome/js/solid.js"></script>
<script defer src="/your-path-to-fontawesome/js/fontawesome.js"></script>

I'm not entirely clear how to translate that to importmap. I tried:

<script defer src="https://ga.jspm.io/npm:@fortawesome/[email protected]/js/brands.js"></script>
<script defer src="https://ga.jspm.io/npm:@fortawesome/[email protected]/js/solid.js"></script>
<script defer src="https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js"></script>

since the pinning resulted in:

pin "@fortawesome/fontawesome-free", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js"

but that doesn't work. It fails with this error in the console in the browser:

enter image description here



Solution 1:[1]

I wrote a longer piece about this on my blog, but the gist is copied here.

I just made it work but I'm not entirely sure why it works so I would appreciate any insight or improvements on this solution. In the meantime, I'm happy to share with the world:

First, you need to pin the Font Awesome Javascript packages by running:

./bin/importmap pin @fortawesome/fontawesome-free @fortawesome/fontawesome-svg-core @fortawesome/free-brands-svg-icons @fortawesome/free-regular-svg-icons @fortawesome/free-solid-svg-icons

which adds:

pin "@fortawesome/fontawesome-free", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js"
pin "@fortawesome/fontawesome-svg-core", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/index.es.js"
pin "@fortawesome/free-brands-svg-icons", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/index.es.js"
pin "@fortawesome/free-regular-svg-icons", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/index.es.js"
pin "@fortawesome/free-solid-svg-icons", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/index.es.js"

to your importmap.rb.

Then in your app/javascript/application.js you need to add:

import {far} from "@fortawesome/free-regular-svg-icons"
import {fas} from "@fortawesome/free-solid-svg-icons"
import {fab} from "@fortawesome/free-brands-svg-icons"
import {library} from "@fortawesome/fontawesome-svg-core"
import "@fortawesome/fontawesome-free"
library.add(far, fas, fab)

If you don't need one of the libraries you can skip them, but skipping the last two imports or adding each icon package to the library makes it not work.

Solution 2:[2]

# tldr

# config/importmap.rb
pin "@fortawesome/fontawesome-free",
  to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/all.js"

# app/javascript/application.js
import "@fortawesome/fontawesome-free";

Based on documentation, we need to load js/all.js from fontawesome package to load all icons https://fontawesome.com/docs/web/setup/host-yourself/svg-js#add-font-awesome-files-to-your-project.

You must have javascript_importmap_tags in your layout for this to work.

Pin fontawesome:

$ bin/importmap pin @fortawesome/fontawesome-free
Pinning "@fortawesome/fontawesome-free" to https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js

That command doesn't pin the correct file, so we need to change it:

# config/importmap.rb

# NOTE: change `fontawesome.js` to `all.js`
pin "@fortawesome/fontawesome-free",
  to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/all.js"

Import it in application.js:

// app/javascript/application.js

import "@fortawesome/fontawesome-free"; // => https://ga.jspm.io/npm:@fortawesome/[email protected]/js/all.js

Everything should work now.

Other options.

Alternatively, import pinned module in the layout instead of application.js:

<%= javascript_import_module_tag "@fortawesome/fontawesome-free" %>

To load only certain styles, we need to load solid.js, brands.js, and fontawesome.js separately.

Pin fontawesome and don't change it:

$ bin/importmap pin @fortawesome/fontawesome-free
Pinning "@fortawesome/fontawesome-free" to https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js

Pin solid.js:

$ bin/importmap pin @fortawesome/fontawesome-free/js/solid.js
Pinning "@fortawesome/fontawesome-free/js/solid.js" to https://ga.jspm.io/npm:@fortawesome/[email protected]/js/solid.js

Pinned name is a bit verbose, so we could rename it:

pin "@fortawesome/fontawesome-free/solid", to: "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/solid.js"

Import it in application.js:

// app/javascript/application.js

import "@fortawesome/fontawesome-free/solid";  // => https://ga.jspm.io/npm:@fortawesome/[email protected]/js/solid.js
import "@fortawesome/fontawesome-free";        // => https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js

Do the same for brands.js if needed.

You should end up with something like this in your rendered layout:

<script type="importmap" data-turbo-track="reload">{
  "imports": {
    "application": "/assets/application-66ce7505c61e3e4910ff16e7c220e1fbfb39251cd82e4bab8d325b3aae987cf9.js",
    "@fortawesome/fontawesome-free": "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/fontawesome.js",
    "@fortawesome/fontawesome-free/solid": "https://ga.jspm.io/npm:@fortawesome/[email protected]/js/solid.js",
}</script>

<script type="module">import "application"</script>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Alex