Using local fonts with Webpack / Webpacker

Updated . Posted . Visible to the public.

When we want to use our own (or bought) fonts in an application with Webpack(er), we have two options. We can

  • put the fonts directly into your Webpack's assets folder or
  • write an npm package with an own sass file that can be imported from the Webpack manifest.

Load fonts from your assets folder

The first option turns out to be straightforward: Import the stylesheets in the index.js of the pack you're using:

// webpack_source_path/application/index.js

import './stylesheets/reset'
import './stylesheets/main' // loads the fonts in
let stylesheetsContext = require.context('./stylesheets/blocks', true, /\.sass$/)
for(let key of stylesheetsContext.keys()) { stylesheetsContext(key) }
// webpack_source_path/application/stylesheets/main.sass

@import 'font_faces'

html
  font-family: MyFont, Arial
// webpack_source_path/application/stylesheets/_font_faces.sass

@font-face
  font-family: 'MyFont'
  src: url('../fonts/my_font.ttf')

Webpack will replace ../fonts/my_font.ttf with the compiled filepath (something like media/application/fonts/my_font-f99f9d50a569dbcf72e3084ef1a43208.ttf) and you're good.

Load fonts as an npm package

The second option is handy when you're dealing with fonts that are not maintained by yourself but neither are available on npm. In our case, we purchased a font that had hashed filenames for each font version (normal, bold, ...). You don't want to mess around with assets you don't maintain, so renaming them is not a good option. Neither is inserting cryptic filenames to your code a good manner, it can affect readability in a terrible way.
The better option is to bundle your local font into an npm package and to add a dependency in your project's package.json file which loads this bundled font:

// ./package.json

{
  "name": "my_project",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "^3.0.2",
    "bought-font": "file:vendor/asset-libs/bought-font"
  },
  "devDependencies": {
    "webpack-dev-server": "^2.9.5"
  }
}

Note the path's prefix file: in the dependency of 'bought-font', which tells Webpack to not search npm for a matching package, but to look for a local directory.
The directory you are pointing to should also contain a package.json file so Webpack can interpret the folder as an npm package.

// vendor/asset-libs/bought-font/package.json

{
  "name": "bought-font",
  "version": "1.0.0",
  "description": "",
  "main": "index.scss",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Salesman of trust",
  "license": "LICENSE",
  "private": true
}

Webpack will now handle the font as a package and you can import the shipped scss/sass/css file, which contains the font-faces, in your pack's manifest and just use the defined fonts in your application:

//webpack_source_path/application/index.js

import 'bought-font/index.scss'
Jakob Scholz
Last edit
Jakob Scholz
Keywords
webpack, webpacker
License
Source code in this card is licensed under the MIT License.
Posted by Jakob Scholz to makandra dev (2019-03-22 10:52)