Adding scss assets to Angular library
Tags: angular, scss, library, webdev
Published: 2023-11-30 15:10:22

In a previous article, I was talking about some ways to [include assets in an Agular library](https://medium.com/@coco-boudard/adding-css-assets-to-angular-library-c22fd3a47c5d). Let’s go a little further, and see how we can handle scss files and compile in the application and not in the library.

### The example of bootstrap
One example we can name is how we can integrate bootstrap style to our application. It goes like this :

- Install bootstrap
- Reference bootstrap scss in angular.json or global styles.scss
- Eventually override some variables of the library

> **Note**: if you import such a scss file like bootstrap, you may override some variables, only if you import the stylesheet in your styles.scss (or another one) of your project. It won’t work from angular.json.


![This way we can override variables used in bootstrap scss.](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2rrhs8sdpsefqjzlosm6.png)

### The goal of our application
The main goal here is to have an Angular application that doesn’t require the library scss to be previously built. We will see what options we have to let the application do the job. The library will not only expose **scss** files but also **images** and **fonts**.

This means that our library will not expose compiled css to the outer world, but sometimes, and it can be convenient, a library can expose both the scss **and** the css.

Of course that means that each time our application will build, this task will be running, but as we might already know, Angular build system does separate typescript and style build.

## The Angular workspace
Let’s create a workspace with both a library and an application.

```
ng new ng-assets-wk --create-application false
cd ng-assets-wk
ng g library @abo/ng-lib
ng g application ng-app -routing --style scss
```

We can write some scripts to build both library and application :
```
"build:lib": "ng build --project @abo/ng-lib",
"watch:lib": "ng build --watch --configuration development --project @abo/ng-lib",
"build:app": "ng build --project ng-app",
"watch:app": "ng build --watch --configuration development --project ng-app",
```

### Styles in the application
In the `src/styles.scss` file, we can add some basic style and reference a simple asset with variables.


![Override scss variables from Angular library](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izsmjphzll5pq7ojg35y.png)
When we compile the application in `watch` mode, we see that chunks are produced, both `js` and `css` files.

![Differential build of Angular resources](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/amfrqu8ztnmf7q8457uw.png)
What can seem weird, is that when you modify your scss files (main file or variables), the message is pretty simple and doesn’t reflect the fact that `styles.css` output has indeed been updated.

![Angular build output after styles.scss modification
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r4vmwbvdyml87ap4lv5g.png)
Let’s note that there is a difference in the build output when you alter any of the source code, like a component, wether it’s `typescript`, `html` template or `scss` file, which are not processed like the stylesheets referenced in `angular.json` configuration file in the styles section :

![Angular build output after component modification
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gpb141boiibasc1w4auk.png)

This makes sense because Angular uses a default configuration for style isolation which is encapsulation: [ViewEncapsulation.Emulated](https://angular.io/guide/view-encapsulation) that would prevent styles declared for a component to spread to other components.

### Styles in the library
Ok, now we want to add scss files to our library, and expose them to our application. Let’s create an assets folder in the libray and put some files in it:

![Declare scss variables in Angular library](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nqodmlzz2oarn76i7w8z.png)

> **Note**: if you want to be able to override your scss variables, you would need to use the keyword `!default` like here, in the first declaration of your variable.

Let’s add this folder, and all files in it, to the `ng-package.json` file of the library. You can [find more information here](https://github.com/ng-packagr/ng-packagr/blob/main/docs/copy-assets.md) about why we should declare this `assets` property.

```
  "assets": [
    "./assets/**/*.*"
  ]
```

During the **build of the library**, the folder should be exported in the dist folder. Following a [previous article about Angular libraries](https://medium.com/@coco-boudard/using-angular-cache-with-library-1744e5b8627b), we will publish on a local **Verdaccio server**. Now we can add the scss file to the list of styles of our application in the `angular.json` (the point is to be as close as a production ready use case).

```
"unpublish:lib": "npm unpublish @abo/ng-lib --registry http://localhost:4873/ --force",
"publish:lib": "ng build @abo/ng-lib && cd dist/abo/ng-lib && npm publish --registry http://localhost:4873/",
"install:lib": "npm install @abo/ng-lib --registry http://localhost:4873/",
```

> Don’t forget to remove the reference to the library path in the `tsconfig.json` file.


![angular.json scss reference of the library](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9igbue2fvd5qghv8x3r8.png)

**Note**: if you build your application in production mode, you might see something weird in the code inspector : the styles appear twice :

![Angular inlineCritical configuration effect](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tace6z532aehy8ep5t30.png)
This is due to an implicit configuration in `production` build mode called **inlineCritical** (turn this to false to disable if you want) that is meant to reduce the initial styled render of the page :

```
"optimization": {
  "styles": {
    "minify": true,
    "inlineCritical": true
  }
}
```

Anyway, if we run our application, the style of the library should be compiled with our application and be applied. Since we want to **override the variables**, let’s try to use this stylesheet in our main `styles.scss` file.

We remove the reference in the `angular.json` file. Then we add a reference in the `styles.scss` file :

![Add the library scss file in global application styles](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/om17phg936eqon28dnfe.png)

This is working, obviously, but it doesn’t look great DX wise, so we will use the [export property of the Angular package format](https://angular.io/guide/angular-package-format#exports), in order to declare how we can access our scss resources. In this Angular documentation, it states that you need to declare this `exports` property. As a result, we can use the entrypoint of the library in the scss import statement.

![package.json of the library and styles.scss of the application
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0xp0v5rdmfwtnx9gvf5x.png)
This import is way much cleaner right ?

### Add other files to the scss package
Now, let’s add the most used files in combination with css: **fonts and images**.

In our library `assets` folder, we can add an `/img` folder with images, here we add two logos of Angular, and then we can simply reference these images in any CSS rule that we see fit.

![Simple css rules to use images in our components](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bpfiupikmdxde5boqxem.png)
Now we should be able to see our images in the page with some simple code :

```
<h1 class="logo next">Angular next</h1>
<h1 class="logo">Angular</h1>
```

![Angular logos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w9xjii28mtftq3823si2.png)
Now let’s add a custom font of our choice. Let’s go with [Segoe UI font](https://www.dafontfree.io/segoe-ui-font/). In our library `assets` folder, we can add an `/fonts` folder with the desired files. For the sake or readability, let’s create a dedicated `_fonts.scss` file and reference it in our main library scss file.

![scss fonts file in the angular library
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b7rk9ytx8j3mo69ogz2v.png)
In our main scss files, we import the fonts definition, and use the font in the body for a start, but anywhere you would want :

![Use the library font in the app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2er25fy6lnv5e12yyny7.png)
Now we can test in the browser if everything is ok, the font should be loaded in the devtools.

![The font from the library is loaded in the app
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mwy03uqdkqhyz316r82s.png)

### Use the library scss in application components
We saw that the components scss are not processed like the main styles declared from `angular.json` section. But we still can use our declared variables (or any kind of tool, like mixin for example) in our components.

Without any modification we could use the `@use` annotation and consume our variables like that :

```
@use "node_modules/@abo/ng-lib/assets/lib-variables" as lib;
```

![You can use @use or @import for the angular library scss
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tz9wo4ibrspct5htyscx.png)
But again, that’s not very nice, we can then add another entry in our library package.json and have a better import in our component’s scss :

![Expose scss variables from the angular library
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/90zk78zilv7ujmrxz9ip.png)
With the same pattern, we can declare a `mixins` file and use it through an export entry :

![Declare scss mixins in the angular library
](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lc9kc2ibb4om8z12eppt.png)

## Conclusion
We saw that having a clean Angular library exposing scss resources is quite easy to configure. The main advantage of this method is to get rid of the css pre-build task in the library, and the maintainability of our custom variables and other uses of scss files. This is possible thanks to the scss capabilities of the Angular build, since we never had to launch a dedicated sass build.

The use of the Angular endpoint reference is a plus for any library publisher.

### References

https://github.com/aboudard/ng-assets-wrk

https://github.com/ng-packagr/ng-packagr/blob/main/docs/copy-assets.md