javascriptangularbundling-and-minification

how to bundle a module/component to js and use in another angular project?


I was just trying to build a module/component and serve it as a JS bundle. it builds:

@Component({
  selector: 'app-component-overview',
  template: '<button><ng-content></ng-content></button>',
})
export class ButtonComponent {}

@NgModule({
  declarations: [ButtonComponent],
})
export class AppModule {}

the issue is that after building it to a javascript bundle. when I try to import it in another angular project. I get:

//ERROR in ... error TS2306 '...' is not a module.
   loadChildren: () => import('...').then(m=>m.ButtonModule)

maybe I am missing the point here and things are different in angular, having webpack control makes it a lot easier but I want to avoid bringing custom builders and fiddling with the settings as little as possible.

Question is, is there a well documented way to bundle a module or even a standalone component to be used outside my project as a JS bundle? I could not find anything useful other than high level explanation of reusing and lazyloading thing already inside the same project.


Solution

  • After a few hours browsing around. I figured it out.

    The answer that @json-derulo gave is part of the solution but there are more steps to make this work.

    1. follow the guide: https://angular.io/guide/creating-libraries here is the tricky part if you import the lib inside the workspace it will work. but that does not make much sense. You likely have another repository with a angular app that you want to consume the lib.
    2. now to be able to import the this component as a lazy loaded route you will need to add "@angular/router" to the lib peerDependecies and run npm install again
    3. now create a routing module and add the empty path to point to the component in the lib.
    //my-lib-routing.module.ts
    import { NgModule} from "@angular/core";
    import { RouterModule } from "@angular/router";
    import { MyLibComponent } from "./my-lib.component";
    
    const routes= [
     { path: '', component: MyLibComponent },
    ];
    
    @NgModule({
     imports: [
       RouterModule.forChild(
         routes,
       )
       // other imports here
     ],
     // providers: [RouterModule],
     exports: [RouterModule]
    
    })
    export class myLibRoutingModule { }
    
    1. change the libmodule to import the routing module
    //
    import { NgModule } from '@angular/core';
    import { myLibRoutingModule } from './my-lib-routing.module';
    import { MyLibComponent } from './my-lib.component';
    
    
    
    @NgModule({
      declarations: [MyLibComponent],
      imports: [
        myLibRoutingModule
      ],
    })
    export class MyLibModule { }
    
    
    1. on the lib project root run 'npm run build'.
    2. create a separate repo and "ng new app"
    3. add the lib to the package.json of the main app, something like "my-lib": "../my-lib-ws/dist/my-lib".
    4. open angular.json and add "preserveSymlinks": true to the build options.
    5. run npm i to link the lib as a dependency.
    6. add the libmoudle as a lazy loaded route
    import { NgModule } from '@angular/core';
    import { Routes, RouterModule } from '@angular/router';
    
    
    const routes: Routes = [
     {path: 'test', loadChildren: () => import('my-lib').then(m=>m.MyLibModule)}
    ];
    
    @NgModule({
     imports: [RouterModule.forRoot(routes)],
     exports: [RouterModule]
    })
    export class AppRoutingModule { }
    
    
    1. run npm run start. and try to access the 'test' route. you should see the component loaded in the main app router outled

    Now, this is more of learning exercise the bundles almost gets doubled. and you would profit more using module federation. But it is a use case we have. Anyhow the steps are here if anyone can't reproduce let me know.