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.
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.
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.
Let’s create a workspace with both a library and an application.
ng new ng-assets-wk --create-application false
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",
src/styles.scss file, we can add some basic style and reference a simple asset with variables.
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
html template or
scss file, which are not processed like the stylesheets referenced in
angular.json configuration file in the styles section :
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.
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:
Note: if you want to be able to override your scss variables, you would need to use the keyword
!defaultlike 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
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/",
Don’t forget to remove the reference to the library path in the
Note: if you build your application in production mode, you might see something weird in the code inspector : the styles appear twice :
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
We remove the reference in the
angular.json file. Then we add a reference in the
styles.scss file :
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.
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.
<h1 class="logo next">Angular next</h1>
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.
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;
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.