'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:
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 |