Ciel
Ciel

Reputation: 4440

Angular 7 library - how to bundle dependencies without adding them to the main app

I have an Angular 7 application that I created with the @angular/cli and then I added a library to using ng generate library. It works fine in dev mode and such. There's no problems.

I'd like to keep the dependencies that are relevant to the library contained to it; And not clutter up the main application's package.json. So, naturally, I did npm install --save [xyx] to the library folder. That worked fine. Still runs great in dev mode.

But when I try to do ng build --prod, suddenly it can't find the dependencies that are part of the library. The reason why is obvious, of course; They're not being properly bundled in. I've investigated npm's bundleDependencies feature to no avail, and I've looked at the lib: { embedded: ... } and whitelistedNonPeerDependencies option for ng-package.json, but I can't seem to make any of them do quite what I want.

This isn't a make or break requirement; If it's absolutely mandatory, I will just install the dependencies in the main application. But I'd very much like to avoid that. Perhaps it's an unreasonable goal, I am unsure.

Any help would be greatly appreciated.

Upvotes: 17

Views: 5914

Answers (2)

peinearydevelopment
peinearydevelopment

Reputation: 11474

I tried to do what you described locally and didn't have an issue. Here were the steps I took.

  1. npm install @angular/cli
  2. node_modules/.bin/ng new installtest
  3. cd installtest
  4. node_modules/.bin/ng generate library libtest
  5. cd projects/libtest
  6. npm install --save numeral
  7. npm install --save-dev @types/numeral
  8. added ro.pipe.ts to projects/libtest/src

    import { Pipe, PipeTransform } from '@angular/core';
    
    import * as numeral from 'numeral';
    
    @Pipe({name: 'decimalUnit'})
    export class RoPipe implements PipeTransform {
      constructor() {
        numeral.register('locale', 'ro', {
            delimiters: {
                thousands: '.',
                decimal: ','
            },
            abbreviations: {
                thousand: 'k',
                million: 'm',
                billion: 'b',
                trillion: 't'
            },
            ordinal: function (number) {
                return number === 1 ? 'er' : 'ème';
            },
            currency: {
                symbol: 'RON'
            }
        });
    
        numeral.locale('ro');
    }
    
      public transform(value: string, numDecimals: number) {
        const b = numeral(value);
        let x = '0,0.';
        for (let i = 0; i < numDecimals; i++) {
            x = x + '0';
        }
    
        return b.format(x);
      }
    }
    
  9. update projects/libtest/src/lib/libtest.module.ts

    import { NgModule } from '@angular/core';
    import { LibtestComponent } from './libtest.component';
    import { RoPipe } from './ro.pipe';
    
    @NgModule({
      declarations: [LibtestComponent, RoPipe],
      imports: [
      ],
      exports: [LibtestComponent, RoPipe]
    })
    export class LibtestModule { }
    
  10. update projects/libtest/src/public_api.ts

    export * from './lib/libtest.service';
    export * from './lib/libtest.component';
    export * from './lib/libtest.module';
    export * from './lib/ro.pipe';
    
  11. update tsconfig.json. add "projects/libtest/node_modules/@types" to "typeRoots" array

  12. update src/app/app.module.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { LibtestModule } from 'projects/libtest/src/public_api';
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        LibtestModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    
  13. update src/app/app.component.html

    <label>{{ '12345678' | decimalUnit:2 }}</label>
    <br>
    <label>{{ '12345678' | decimalUnit:0 }}</label>
    <br>
    <label>{{ '12345678' | decimalUnit:2 }}</label>
    <br>
    <label>{{ '12345678' | decimalUnit:2 }}</label>
    <br>
    <label>{{ '12345678' | decimalUnit:2 }}</label>
    

After this, I ran npm run start to verify that it works with the dev build. Next I ran npm run start -- --prod to verify that it works with the prod build. Both worked. The last thing I did was to run npm run build and npm run build -- --prod and loaded the website through IIS, both of which worked. I put the full repo project on GitHub for reference.

You don't really provide an MVCE. So it is hard to tell you why your particular project isn't working at the moment. If the above steps don't work for you, please provide more detail as to what you have tried exactly that is failing(or at least a minimal project that can reproduce the issue you are encountering).

Upvotes: 8

Robin Dijkhof
Robin Dijkhof

Reputation: 19288

As far as I know this is not possible.

To somewhat solve your "problem" you could create a completly new cli project. In the new project generate your library and other future libraries. The new project can be some showcase/docs for your libraries. This way all of your libraries will use the same version of dependencies but are not included into your main application.

Upvotes: 0

Related Questions