I have an Angular 7 component library that uses FontAwesome icons.
First of all, output of ng version
:
Package Version
------------------------------------------------------------
@angular-devkit/architect 0.10.7
@angular-devkit/build-angular 0.10.7
@angular-devkit/build-ng-packagr 0.10.7
@angular-devkit/build-optimizer 0.10.7
@angular-devkit/build-webpack 0.10.7
@angular-devkit/core 7.0.7
@angular-devkit/schematics 7.0.7
@angular/cdk 7.1.1
@angular/cli 7.0.7
@angular/compiler-cli 7.0.4
@angular/language-service 7.0.4
@angular/material 7.1.1
@ngtools/json-schema 1.1.0
@ngtools/webpack 7.0.7
@schematics/angular 7.0.7
@schematics/update 0.10.7
ng-packagr 4.4.5
rxjs 6.3.3
typescript 3.1.3
webpack 4.19.1
And relevant tidbits in package.json
:
"@fortawesome/angular-fontawesome": "^0.3.0",
"@fortawesome/fontawesome-svg-core": "^1.2.8",
"@fortawesome/free-regular-svg-icons": "^5.5.0",
"@fortawesome/free-solid-svg-icons": "^5.5.0",
Here's my module definition:
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { library } from '@fortawesome/fontawesome-svg-core';
import { faAngleDown } from '@fortawesome/free-solid-svg-icons/faAngleDown';
import { faBars } from '@fortawesome/free-solid-svg-icons/faBars';
import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons/faCalendarAlt';
import { faCaretLeft } from '@fortawesome/free-solid-svg-icons/faCaretLeft';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons/faChevronDown';
import { faSortUp } from '@fortawesome/free-solid-svg-icons/faSortUp';
import { faSortDown } from '@fortawesome/free-solid-svg-icons/faSortDown';
import { faChevronUp } from '@fortawesome/free-solid-svg-icons/faChevronUp';
import { faChevronLeft } from '@fortawesome/free-solid-svg-icons/faChevronLeft';
import { faTimes } from '@fortawesome/free-solid-svg-icons/faTimes';
import { faUser } from '@fortawesome/free-solid-svg-icons/faUser';
import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons/faSignOutAlt';
import { faQuestionCircle } from '@fortawesome/free-solid-svg-icons/faQuestionCircle';
import { faGlobeAmericas } from '@fortawesome/free-solid-svg-icons/faGlobeAmericas';
<app imports>
library.add(
faAngleDown, faBars, faCalendarAlt, faCaretLeft, faChevronDown,
faChevronLeft, faChevronUp, faGlobeAmericas, faQuestionCircle,
faSignOutAlt, faSortDown, faSortUp, faTimes, faUser
);
@NgModule({
declarations: [
<app components>
],
exports: [
<app components>
],
imports: [
FontAwesomeModule,
<other app imports>
]
})
export class LibModule {
public static forRoot(): ModuleWithProviders {
return {
ngModule: LibModule,
providers: [
<some providers>
]
};
}
}
Here's public_api.ts
:
export * from './lib/lib.module';
<component exports>
I can build this module with ng build mylib --prod
just fine. However, when I try to use it in an application, whenever the --prod
flag is used to build or serve, I get the following errors:
FontAwesome: Could not find icon with iconName=times and prefix=fas
Here's the app.module.ts
file for the application:
import { faCalendarAlt } from '@fortawesome/free-solid-svg-icons';
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { LibModule } from 'libmodule';
<app imports>
library.add(faCalendarAlt);
@NgModule({
bootstrap: [ AppComponent ],
declarations: [
AppComponent,
],
imports: [
FontAwesomeModule,
LibModule.forRoot(),
]
})
export class AppModule {
}
app.component.ts
is using the faCalendarIcon
, and also bringing in components from LibModule
which in turn are using the icons described in the lib module definition.
The calendar icon displays just fine when using ng serve --prod
or ng build --prod
and then serving the application not through the baked angular dev server. However, every icon used by the library components themselves don't show up, and I see the error from the title in the console for every one of them.
Please note that this doesn't happen when I use ng serve
without the prod flag, so it may have something to do with tree-shaking?
How can I use FontAwesomeModule within a library and make sure that the consumers of the library can see the icons as well? I'd rather not have to make all consumers import all icons used by the library.
Note that I'm using deep imports with my FontAwesome icons, I've also tried to do "shallow" imports as such:
import {
faAngleDown,
faBars,
faCalendarAlt,
faCaretLeft,
faChevronDown,
faChevronLeft,
faChevronUp,
faGlobeAmericas,
faQuestionCircle,
faSignOutAlt,
faSortDown,
faSortUp,
faTimes,
faUser
} from '@fortawesome/free-solid-svg-icons';
I've also tried for my lib module to export FontAwesomeModule, and not to export it. I've tried exporting each icon, but that's not possible it seems.
OK, we figured it out internally.
In the library, the library.add(...)
statements that were just floating in the library module definition file need to move to the module constructor. This solves the issue.
There is another option.
ng new ng-fontawesome
ng generate library ng-fa
npm install --save @fortawesome/angular-fontawesome @fortawesome/fontawesome-svg-core @fortawesome/free-regular-svg-icons
Update projects/ng-fa/src/lib/ng-fa.module.ts
to import/export the fontawesome module
import { NgModule } from '@angular/core';
import { NgFaComponent } from './ng-fa.component';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
@NgModule({
declarations: [NgFaComponent],
imports: [FontAwesomeModule],
exports: [NgFaComponent, FontAwesomeModule]
})
export class NgFaModule { }
Update projects/ng-fa/src/lib/ng-fa.component.ts
to utilize a fontawesome icon
import { Component } from '@angular/core';
// import { IconDefinition } from '@fortawesome/fontawesome-common-types';
import { faAddressBook } from '@fortawesome/free-regular-svg-icons';
@Component({
selector: 'lib-ng-fa',
template: `
<fa-icon [icon]="icon"></fa-icon>
`,
styles: []
})
export class NgFaComponent {
// icon: IconDefinition = faAddressBook;
icon = faAddressBook;
}
Update src/app/app.module.ts
to import your library module by name(not relative path)
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { NgFaModule } from 'ng-fa';
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule, NgFaModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
Add npm scripts to cause the library to be built before the application is. In the scripts
tag in the main package.json
file I added to entries.
"build:ng-fa": "ng build ng-fa"
"prestart": "npm run build:ng-fa"
I tested this with the start command but you would need to do the same thing for your build command.
I then ran npm run start
(dev) and npm run start -- --prod
to test both builds and they are working fine. This greatly reduces the need for all of the imports as you are doing it above. Here you only need to import the icons in the components that actually need them(not in the module as well).
I have created a GitHub repo with this sample as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With