How to include FontAwesome in Phoenix app?

Hi,

I am completely clueless when it comes to the whole static assets building pipeline. That’s probably the most overwhelming programming experience in my career thus far :joy:

Seriously though, can anyone please share a snippet of things I need to add to have FontAwesome icons available in a phoenix app?

I’m using Phoenix 1.4.0 so I guess that’s webpack then, plus I do npm install in assets directory to get the priv contents built. Everything is pretty much at mix phx.new defaults. Pls send halp.

1 Like

You enter assets directory and then follow NPM instructions. That is it. Phoenix assets pipeline is exactly the same way as any other webpack project with specific build directory (../priv/static) and that is all.

1 Like

Hi, when it comes to icons, fonts or heavy dependencies it’s a good idea to serve those assets using their respective CDNs, so I’d rather add a simple link tag to include Font Awesome. You should only serve by yourself those dependencies that you want to customize.

2 Likes

You enter assets directory and then follow NPM instructions . That is it.

I wish. Nothing related to font awesome ends up in priv/static after doing just that.

“Same way as any other webpack project” means nothing to me unfortunately.

3 Likes

That makes sense, I’ll see if I can just put those pre-built assets on S3 due to privacy concerns.

Have you restarted your application? It need to be rebuilt after the fact.

You might need something like File Loader to manage the kinds of assets FontAwesome provides. This guide seems to go over using Font Awesome and File Loader.

1 Like

I have this loader for fonts in my webpack.config.js, in the modules/rules section

      // Load fonts
      {
        test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?(\?.*$|$)/,
        use: 'url-loader?&limit=10000&name=/fonts/[name].[ext]',
      },
      {
        test: /\.(eot|ttf|otf)?(\?.*$|$)/,
        loader: 'file-loader?&limit=10000&name=/fonts/[name].[ext]',
      },

Then in app.js, I load app.scss, and in app.scss, I load fontawesome, something like this…

@import '../../node_modules/font-awesome/css/font-awesome.css';

But for this to work, I added following dev dependencies,

node-sass, sass-loader, file-loader, url-loader.

You might show your webpack.config.js, and your package.json.

1 Like

Another option is to download individual font awesome icons as SVGs into assets/static/images and them emit them in your templates or views with Phoenix Inline SVG.

If you only want a few icons, this can reduce the size of your responses and doesn’t involve any webpack stuff. Caveats: some older browsers have issues with SVG, and every time you want a new icon, you have to download it and add it to your assets directory.

3 Likes

Thank you, that worked!

Navigate to your phoenix app assets directory:

cd your_app/assets

Install free edition of fontawesome as explained here:

npm install --save-dev @fortawesome/fontawesome-free

You will see package.json updated with a new entry:

..
"devDependencies": {
    "@babel/core": "^7.0.0",
    "@babel/preset-env": "^7.0.0",
    "@fortawesome/fontawesome-free": "^5.9.0",
...

You will have to install file-loader package as well: npm install file-loader.

Then modify webpack.config.js to be able to copy awesome fonts and extract SCSS files:

module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      },
      {
        test: /\.(css|sass|scss)$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
      },
      {
        test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,
        use: [{
          loader: 'file-loader',
          options: {
            name: '[name].[ext]',
            outputPath: '../fonts'
          }
        }]
      }
    ]
  },
...

Next, modify your app.scss file as follows (I also use Bootrstrap, so remove the related import if you don’t use it):

@import "custom";
@import "~bootstrap/scss/bootstrap";
@import "~@fortawesome/fontawesome-free/scss/fontawesome";
@import "~@fortawesome/fontawesome-free/scss/regular";
@import "~@fortawesome/fontawesome-free/scss/solid";
@import "~@fortawesome/fontawesome-free/scss/brands";

And finally, my _custom.scss file (remove $primary containing line, it is for Bootrstap override):

/* Boostrap overrides */

$primary: #F92653;

/* Fontawesome 5 config */

$fa-font-path: "~@fortawesome/fontawesome-free/webfonts"

Hope, this helps.

14 Likes

I followed the steps suggested by @belgoros, but my icons are not rendering. I just get a little box with the hex codes for the icons. Webpack is running without errors, but I don’t think the browser is loading the fonts. I think the issue is the @font-face section in my css, which looks like this:

@font-face {
 font-family:'Font Awesome 5 Free';
 font-style:normal;
 font-weight:400;
 font-display:block;
 src:url([object Object]);
 src:url("[object Object]?#iefix") format("embedded-opentype"),
 url([object Object]) format("woff2"),
 url([object Object]) format("woff"),
 url([object Object]) format("truetype"),
 url("[object Object]#fontawesome") format("svg")
}

It looks like webpack is not putting in the URL for the fonts correctly. I barely understand how webpack works, and I’ve already been banging my head against this for too long. Maybe someone has a suggestion?

Just do never integrate FontAwesome through one of their CDN, their Kit, their font, or whatnot. It’s terrible.

Last time I tried to integrate FA into my website, through the official recommended way, it drastically decreased my page’s loading time. Just because I was using 3 icons. The Network tabs showed a huge number of requests being made. Your page should never suffer because of some icons, this is not acceptable, and it happened to many people => google performance issue with FA integration.

Either they don’t care too much about free users, or they have (had?) a bug. This happens to free users only. In any case, trust lost.

Use a tool like Icomoon for example, and you can only package the few icons your app needs. But make sure to check the licence for FA icons; using directly their SVG is restricted to some paid subscription. But for me there’s no other way, lesson learned.

I did integrate FontAwesome in my project very differently.
It seems that Phoenix(1.5.0) already shipped with webpack along with a bunch of loaders like node-sass, css-loader, etc.
I downloaded the fontawesome zip as a whole and dumped the scss and webfonts folders in my /assets/css directory so it looks like this

proj/assets/css/fontawesome/scss/<all scss files>
proj/assets.css/fontawesome/webfonts/<all webfonts files>

Next, I had to go to my app.scss and load fontAwesome.
I also had to specify the $fa-font-path before doing the imports above since I am using a customized directory structure and FontAwesome needs to load webfonts to make it work:

$fa-font-path: "./font-awesome/webfonts";
@import "./font-awesome/scss/fontawesome";
@import "./font-awesome/scss/solid";

Next, Webpack complained it was missing a couple of loaders that help with loading fonts?
so I had to install them like this:
npm install --save-dev url-loader
npm install --save-dev file-loader

And that is it. It started working now.

1 Like

An update on a post I made in this thread a while ago:

I stopped using PhoenixInlineSVG and now just stick FontAwesome SVGs in an “icons” directory inside the “templates” directory as a .svg.eex file and render them the way I’d render any template. I currently use one of FontAwesome’s CSS files to style the icons.

It’s simple and flexible and doesn’t require any fonts or JS.

1 Like

Hello @grantwest, I’ve been facing the same issue (this last very annoying hours)

and thanks to your hint about that oddly looking
src:url([object Object]);

I’ve found a S.O. answer pointing to a solution:
adding esModule: false to the file-loader option in webpack.config.js.

I suppose it’s a bit late and you’ll have already fixed that, but for others (and my future self) sanity I’m dropping it here anyway :laughing:

When trying to have Font Awesome in your Pheonix app, what you are really looking for is a Pheonix app that can use external fonts, css etc…
In 1.6, esbuild is capable of that, but not with the default configuration mix phx.new uses to scaffold your fresh app.
I found this Gist extremely useful: ks2211/Phoenix esbuild with Tailwind and Fontawesome
If you need a working sample of a Pheonix 1.6 fresh app working with Font Awesome, check out my public repo almouattaz / SamplePheonix1.6

1 Like