mirror of
https://github.com/LukeHagar/unicorn-utterances.git
synced 2025-12-06 12:57:44 +00:00
224 lines
8.2 KiB
Markdown
224 lines
8.2 KiB
Markdown
---
|
|
{
|
|
title: "Package Font Files on NPM for Angular Usage",
|
|
description: "Do you use custom fonts that you want to share with multiple apps? Learn how to distribute those fonts on NPM and consume them in Angular!",
|
|
published: '2020-11-24T22:12:03.284Z',
|
|
authors: ['crutchcorn'],
|
|
tags: ['angular', 'javascript', 'npm'],
|
|
attached: [],
|
|
license: 'cc-by-4'
|
|
}
|
|
---
|
|
|
|
While working on my company's shared component system, I got a request from our design team. They wanted to keep our branding consistent with internal documents and other assets. As such, they requested we use a font called "Stirling Foundry".
|
|
|
|
While we're prepping our shared component system for an open-source release to the public, we quickly acknowledged that we couldn't possibly ship this font with the package we intend for public publishing [due to it's licensing and cost](https://www.fonts.com/font/the-foundry/foundry-sterling).
|
|
|
|
However, we have multiple teams that rely on our shared component system, and we don't want to have to copy+paste the relevant `@font-face` definition or font files. What was our solution? Ship a second `npm` package (in our internal `npm` registry) that contained all of our private assets - including font files.
|
|
|
|
Let's walk through how we did that.
|
|
|
|
# Setup Assets Package {#assets-package}
|
|
|
|
As we're wanting to ship our packages separately, we opted for two Git repositories for the component system and private assets. In a new repository, I have the following for the `package.json`:
|
|
|
|
```json
|
|
{
|
|
"name": "ecp-private-assets",
|
|
"version": "1.0.0",
|
|
"main": "index.js",
|
|
"scripts": {
|
|
"release": "standard-version"
|
|
},
|
|
"devDependencies": {
|
|
"@commitlint/cli": "^11.0.0",
|
|
"@commitlint/config-angular": "^11.0.0",
|
|
"husky": "^4.3.0",
|
|
"standard-version": "^9.0.0"
|
|
},
|
|
"husky": {
|
|
"hooks": {
|
|
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
|
|
}
|
|
},
|
|
"commitlint": {
|
|
"extends": [
|
|
"@commitlint/config-angular"
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
While this package will not maintain code, I still believe it important to maintain a semver for the package. If a path of the package changes, the semver will communicate that with your package's consumers alongside the changeling. As such, this `package.json` utilizes [Conventional Commit and `commitlint` to auto-generate changelogs and maintain history version](/posts/setup-standard-version/).
|
|
|
|
## Add Font Files {#font-files}
|
|
|
|
The "Foundry Stirling" font that I'm shipping is a combination of 7 `.otf` files. I start by creating a `fonts` directory. Inside that directory, I place the `.otf` files in the `fonts` directory.
|
|
|
|
Once done, your project repo should look something like this:
|
|
|
|
```
|
|
.
|
|
├── CHANGELOG.md
|
|
├── README.md
|
|
├── fonts
|
|
│ ├── foundry_sterling_bold.otf
|
|
│ ├── foundry_sterling_book.otf
|
|
│ ├── foundry_sterling_book_italic.otf
|
|
│ ├── foundry_sterling_demi.otf
|
|
│ ├── foundry_sterling_extra_bold.otf
|
|
│ ├── foundry_sterling_light.otf
|
|
│ └── foundry_sterling_medium.otf
|
|
├── index.js
|
|
├── package-lock.json
|
|
└── package.json
|
|
```
|
|
|
|
## `@font-face` CSS Definition {#css-declare}
|
|
|
|
Now that we have the fonts in their place, we need to create a common `foundry_stirling.css` file to access those fonts from CSS.
|
|
|
|
Because we're planning on using Angular CLI, we'll want to set the `src` property to be prefixed with `/assets/`, since that's where Angular sends it's assets.
|
|
|
|
```css
|
|
/* foundry_stirling.css */
|
|
|
|
@font-face {
|
|
font-family: 'Foundry Sterling';
|
|
font-style: normal;
|
|
/* Light */
|
|
font-weight: 300;
|
|
src: local('Foundry Sterling Light'), local('FoundrySterling-light'), url("/assets/foundry_sterling_light.otf") format('opentype')
|
|
}
|
|
|
|
/* ... */
|
|
|
|
@font-face {
|
|
font-family: 'Foundry Sterling';
|
|
font-style: normal;
|
|
/* Extra-Bold */
|
|
font-weight: 800;
|
|
src: local('Foundry Sterling Extra Bold'), local('FoundrySterling-extra-bold'), url("/assets/foundry_sterling_extra_bold.otf") format('opentype')
|
|
}
|
|
```
|
|
|
|
> While we're using CSS here, if you wanted to set the `src` to a different location for non-Angular projects, you could use a SCSS `@mixin` to define the `@font-face` declarations with a customizable `$base_path`.
|
|
>
|
|
> ```scss
|
|
> @mixin foundry_sterling($base_path) {
|
|
> @font-face {
|
|
> font-family: 'Foundry Sterling';
|
|
> font-style: normal;
|
|
> /* Extra-Bold */
|
|
> font-weight: 800;
|
|
> src: url("#{$base_path}/foundry_sterling_extra_bold.otf") format('opentype')
|
|
> }
|
|
>
|
|
> // ... Other @font-face declarations
|
|
> }
|
|
> ```
|
|
>
|
|
> Then, when consuming the package in your client-side app, you'll want to use something like this:
|
|
>
|
|
> ```scss
|
|
> @include foundry_sterling("/assets")
|
|
> ```
|
|
|
|
### Font Name Value Mapping {#font-val-mapping}
|
|
|
|
Because our font had multiple files to declare the different CSS values weights, we had to declare the `@font-face` for each of the font files. This is the mapping we used:
|
|
|
|
| Value | Common weight name | Related File |
|
|
| ----- | ------------------------- | --------------------------------- |
|
|
| 100 | Thin / Hairline | N/A |
|
|
| 200 | Extra-Light / Ultra-Light | N/A |
|
|
| 300 | Light | `foundry_sterling_light.otf` |
|
|
| 400 | Normal / Regular | `foundry_sterling_book.otf` |
|
|
| 500 | Medium | `foundry_sterling_medium.otf` |
|
|
| 600 | Semi-Bold / Demi-Bold | `foundry_sterling_demi.otf` |
|
|
| 700 | Bold | `foundry_sterling_bold.otf` |
|
|
| 800 | Extra-Bold / Ultra-Bold | `foundry_sterling_extra_bold.otf` |
|
|
| 900 | Black / Heavy | N/A |
|
|
|
|
# Consume Assets Package in Angular CLI {#angular-cli}
|
|
|
|
Now that we have our `npm` package configured for usage, we'll start preparing for consuming that package by installing it into our app's `package.json`:
|
|
|
|
```
|
|
npm i ecp-private-assets
|
|
```
|
|
|
|
> Remember, `ecp-private-assets` is the name of our internal package. You'll need to replace this `npm i` command with your own package name
|
|
|
|
## `angular.json` modification {#angular-json}
|
|
|
|
Once this is done, two steps are required. First, add the following to `angular.json`'s `assets` property. This will copy the files from `ecp-private-assets` to `/assets` once you setup a build.
|
|
|
|
```json
|
|
{
|
|
"glob": "**/*",
|
|
"input": "./node_modules/ecp-private-assets/fonts",
|
|
"output": "./assets/"
|
|
}
|
|
```
|
|
|
|
This way, when we use the CSS `url('/assets/')`, it will point to our newly appointed `fonts` files. Once this is added, your `angular.json` should look like this:
|
|
|
|
```json
|
|
{
|
|
"architect": {
|
|
"build": {
|
|
"builder": "@angular-builders/custom-webpack:browser",
|
|
"options": {
|
|
"customWebpackConfig": {
|
|
"path": "./webpack.config.js"
|
|
},
|
|
"outputPath": "www",
|
|
"index": "src/index.html",
|
|
"main": "src/main.ts",
|
|
"polyfills": "src/polyfills.ts",
|
|
"tsConfig": "tsconfig.app.json",
|
|
"aot": true,
|
|
"assets": [
|
|
"src/assets",
|
|
{
|
|
"glob": "**/*",
|
|
"input": "./node_modules/ecp-private-assets/fonts",
|
|
"output": "./assets/"
|
|
}
|
|
],
|
|
"styles": [
|
|
"src/main.scss"
|
|
],
|
|
"scripts": []
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
## Import CSS {#css-import}
|
|
|
|
Now that we have our assets in place, we need to import the CSS file into our app.
|
|
|
|
|
|
If your app utilizes `postcss`'s `import` plugin or if you're using vanilla CSS, add the following line to your `main.scss` file:
|
|
|
|
```css
|
|
@import "ecp-private-assets/fonts/foundry_sterling.css";
|
|
```
|
|
|
|
> Remember to keep the `@import`s at the top of your file, as you will receive an error otherwise.
|
|
|
|
However, if you're not using `postcss` and have SCSS installed, you can use the following:
|
|
|
|
```scss
|
|
@import '~ecp-private-assets/fonts/foundry_sterling.css';
|
|
```
|
|
|
|
# Conclusion
|
|
|
|
Once you've added the file to your CSS imports and `angular.json`, you should see your font loading as-expected. Because you've setup your fonts to use `npm` to distribute them, you can now reuse your fonts across multiple apps.
|
|
|
|
If you'd like to learn more or have questions about this setup, feel free to leave a comment down below or join [our Discord](https://discord.gg/FMcvc6T) and ask questions there!
|