DEV Community

Cover image for Adding scss assets to Angular library
Alain Boudard
Alain Boudard

Posted on

Adding scss assets to Angular library

In a previous article, I was talking about some ways to include assets in an Agular library. 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.

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
Enter fullscreen mode Exit fullscreen mode

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",
Enter fullscreen mode Exit fullscreen mode

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
When we compile the application in watch mode, we see that chunks are produced, both js and css files.

Differential build of Angular resources
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<br>
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<br>

This makes sense because Angular uses a default configuration for style isolation which is encapsulation: ViewEncapsulation.Emulated 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

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 about why we should declare this assets property.

  "assets": [
    "./assets/**/*.*"
  ]
Enter fullscreen mode Exit fullscreen mode

During the build of the library, the folder should be exported in the dist folder. Following a previous article about Angular libraries, 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/",
Enter fullscreen mode Exit fullscreen mode

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

angular.json scss reference of the library

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
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
  }
}
Enter fullscreen mode Exit fullscreen mode

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

This is working, obviously, but it doesn’t look great DX wise, so we will use the export property of the Angular package format, 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<br>
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
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>
Enter fullscreen mode Exit fullscreen mode

Angular logos
Now let’s add a custom font of our choice. Let’s go with 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<br>
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
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<br>

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;
Enter fullscreen mode Exit fullscreen mode

You can use @use or @import for the angular library scss<br>
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<br>
With the same pattern, we can declare a mixins file and use it through an export entry :

Declare scss mixins in the angular library<br>

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

Top comments (0)