Using Fontsource With 11ty
Tags: webdev, javascript, tutorial, beginners
Published: 2022-12-18 05:34:05

Dealing with fonts can get quite overwhelming. For quite some time, I was searching for a way to self host google fonts because the google fonts API's network request increased the render blocking time more than I expected.

I stumbled upon [fontsource.org](https://fontsource.org) the other day and I found the idea of installing fonts from npm packages appealing.

At first, I used it in my [personal site](https://murtuzaalisurti.github.io) built with [Astro](https://astro.build). The process was incredibly simple. You just have to [import fonts](https://docs.astro.build/en/guides/fonts/#using-fontsource) in your base layout file and that's it. You are ready to use it in your CSS!

```bash
npm i @fontsource/poppins @fontsource/nunito
```

```js
import "@fontsource/poppins"
import "@fontsource/nunito/400.css"
```

I thought what if I could use this in my [11ty blog](https://syntackle.live) too. The next immediate thing which came to mind was to use vite because it can bundle those fonts for me just like Astro.

So, I decided to use [slinkity](https://slinkity.dev/). You can call slinkity as an extension for 11ty projects. It adds more features on the table by post processing your 11ty build output.

Slinkity uses [vite](https://vitejs.dev/) for bundling which is great, but it became a problem for me. I have a relatively old and large project with some custom configurations which came in the way of how vite does things, so migrating to vite resulted in a mess. The migration needs more time. So, I decided to take another approach which might be not so good.

## Using Rollup

[Rollup](https://rollupjs.org/guide/en/) is a javascript bundler you can use to bundle your modules.

```bash
npm install rollup --save-dev
```

I created a rollup config file, named `rollup.config.mjs` at the root of the project.

```js
export default [
    {
        input: "src/js/combine.js",
        output: {
            file: "src/js/minified/index.bundle.js",
            sourcemap: false,
        }
    }
];
```

The idea is to import the fonts just like I did in astro, in a javascript file and then extract css from it in order to copy it in the styles folder.

So, inside the `combine.js` file, I imported some fonts.

```js
import "@fontsource/nunito";
import "@fontsource/poppins";
```

Now, to extract css, I used the [postcss rollup plugin](https://github.com/egoist/rollup-plugin-postcss) and the [rollup copy plugin](https://github.com/vladshcherbin/rollup-plugin-copy) to copy the generated css file to the desired directory. I had to use rollup-plugin-copy because of [this issue](https://github.com/egoist/rollup-plugin-postcss/issues/250).

Installed the following dependencies:

```bash
npm i rollup-plugin-postcss rollup-plugin-copy @rollup/plugin-node-resolve --save-dev
```

The postcss plugin will extract the styles from the javascript file into a new CSS file.

```js
import { nodeResolve } from "@rollup/plugin-node-resolve";
import postcss from "rollup-plugin-postcss";
export default [
    {
        input: "src/js/combine.js",
        output: {
            file: "src/js/minified/index.bundle.js",
            sourcemap: false,
        }
        plugins: [
            nodeResolve(),
            postcss({
                extract: true, // no way to move output to another folder https://github.com/egoist/rollup-plugin-postcss/issues/250
                minimize: true,
            })
        ],
    }
];
```

The next step is to move the CSS file to the desired location because the extracted CSS file will be in the same directory as of the javascript file and you can't specify a location outside the parent folder due to a [bug in the postcss plugin](https://github.com/egoist/rollup-plugin-postcss/issues/250).

```js
import { nodeResolve } from "@rollup/plugin-node-resolve";
import postcss from "rollup-plugin-postcss";
import copy from "rollup-plugin-copy";
export default [
    {
        input: "src/js/combine.js",
        output: {
            file: "src/js/minified/index.bundle.js",
            sourcemap: false,
        }
        plugins: [
            nodeResolve(),
            postcss({
                extract: true, // no way to move output to another folder https://github.com/egoist/rollup-plugin-postcss/issues/250
                minimize: true,
            }),
            copy({
                targets: [
                    {
                        src: "src/js/minified/index.bundle.css",
                        dest: "src/styles/minified",
                        rename: "fonts.bundle.css",
                    },
                ],
                verbose: true,
                hook: "writeBundle",
            })
        ],
    }
];
```

I am running the copy plugin after all the bundles are written and that's why you see the `hook: "writeBundle"` build hook specified for the copy plugin.

Run rollup using this command:

```bash
npx rollup --bundleConfigAsCjs -c
```

Now, the font CSS is ready to use, right? No. There is still one problem.

This is how the generated CSS looks:

```css
@font-face{font-display:swap;font-family:Nunito;font-style:normal;font-weight:400;src:url(files/nunito-cyrillic-ext-400-normal.woff2) format("woff2"),url(files/nunito-all-400-normal.woff) format("woff");unicode-range:u+0460-052f,u+1c80-1c88,u+20b4,u+2de0-2dff,u+a640-a69f,u+fe2e-fe2f}@font-face{font-display:swap;font-family:Nunito;font-style:normal;font-weight:400;src:url(files/nunito-cyrillic-400-normal.woff2) format("woff2"),url(files/nunito-all-400-normal.woff) format("woff");unicode-range:u+0301,u+0400-045f,u+0490-0491,u+04b0-04b1,u+2116}
```

If you look closely at the src url, you will find that the files which the url is referring to are not present in our directory. Yes, the actual font files.

I used `addPassthroughCopy()` in 11ty to copy the required font files from node_modules to the output directory as per the url specified in the font stylesheet.

```js
eleventyConfig.addPassthroughCopy({'./node_modules/@fontsource/poppins/files/*.woff2': 'styles/files'})
```

Copy the required files to the output folder and the fonts are ready to be used.

```css
font-family: "Poppins", "Nunito", sans-serif;
```

## Conclusion

Is this a good solution? I don't know. For me it's more of a hack than a solution and I think there's a better way. Maybe, all we need is a 11ty plugin :)

> *This post was originally published in [Syntackle](https://syntackle.live/blog/using-fontsource-with-11ty-FUzgft/).*