Angular class is not an Angular module

Mark Lisoway picture Mark Lisoway · Jul 20, 2019 · Viewed 8.8k times · Source

When I build my Angular library, publish it to npm, and use it as a dependency in another project, whenever I try to import on of my module classes into my app.module.ts, and get this error Class TekButtonModule is not an Angular module. I have followed steps from multiple different sites on how to create, build, and publish angular libraries, and I can't figure out why it won't recognize the class as a valid module class.

In my app.module.ts, this is how I am importing the module:

import { TekButtonModule } from "tek-angular-uimodules";

@NgModule({
    imports: [
        TekButtonModule
    ]
})
export class AppModule { }

My library project follows the standard directory structure outlined by Angular. I did not change anything with the build, or path settings when I setup the library project. My built library project has a bundles, esm5, esm2015, fesm5, fesm2015, lib (where my custom modules, and components are), as well as a package.json, public-api.d.ts (exports everything in the lib directory), README.md, tek-angular-uimodules.d.ts (exports the public api), and a tek-angular-uimodules.metadata.json file.

Is there some extra configuration that it needed that isn't setup by default to get modules to work correctly?

Here is my button module class:

import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { TekButton } from "./button";

@NgModule({
  declarations: [
    TekButton
  ],
  exports: [
    TekButton
  ],
  imports: [
    CommonModule
  ]
})
export class TekButtonModule {}

Here are some of the files that are generated when I build the project: tek-angular-uimodules.d.ts:

/**
 * Generated bundle index. Do not edit.
 */
export * from './public-api';

public-api.ts

export * from "./lib/button";
export * from "./lib/button-group";
export * from "./lib/nav-bar";

./lib/button/button-module.d.ts

export declare class TekButtonModule {
}

If I import the generated javascript module file from the esm5 directory manually in my app.module.ts file, then it works just fine. But I have to manually do that, when it should just work with the standard module import that WebStorm auto imports for me like any other package.

This is the generated module js file under the esm5 directory:

/**
 * @fileoverview added by tsickle
 * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
 */
import { CommonModule } from "@angular/common";
import { NgModule } from "@angular/core";
import { TekButton } from "./button";
var TekButtonModule = /** @class */ (function () {
    function TekButtonModule() {
    }
    TekButtonModule.decorators = [
        { type: NgModule, args: [{
                    declarations: [
                        TekButton
                    ],
                    exports: [
                        TekButton
                    ],
                    imports: [
                        CommonModule
                    ]
                },] }
    ];
    return TekButtonModule;
}());
export { TekButtonModule };
//# sourceMappingURL=data:application/json;base64

Any help is appreciated. I can provide more code, and screenshots if needed.

This is the error I get when trying to import my module: enter image description here

Answer

Mark Lisoway picture Mark Lisoway · Jul 24, 2019

So I figured out what was causing my specific issue. It was two things. Point two is the direct reason for my issue, point one was making much more confusing to debug.

  1. In order to test my built package, I would run ng build, and then cd into the built project in the dist directory, and run npm pack. I would then install my built package as a file dependency in an entirely separate project to ensure I did everything correctly. What I found out was (or I'm assuming) that there was a caching mechanism going on even when doing local file dependency installations. This caching seemed to be tied to the file name of the tgz file that is generated from npm pack. This caching was causing the very first version to be constantly reinstalled not matter how many changes I made to the built library. The fix, for me, was to simply rename the tgz file to something different each time. You should also change the library version number, and that should also work.
  2. My file structure looked like this:
src
- public-api.ts
- lib
-- button
--- index.ts
--- public-api.ts
--- button.component.ts
--- button.module.ts
-- another-module
-- yet-another-module

The public-api.ts file directly in src looked like this:

export * from './lib/button'
// Other exports

The public-api.ts, and the index.ts file under src\lib\button looked like this:

// public-api.ts
export * from './button.component.ts'
export * from './button.module.ts'

// index.ts
export * from './public-api.ts'

I had assumed that by adding the index.ts files to each directory, the export line in the root public-api.ts would find the index file, and export the files accordingly, but somewhere along the line, this implicit resolution does not work, and, instead, an explicit export is needed. The fix was to change export * from './lib/button' to export * from './lib/button/index.ts' or export * from './lib/button/public-api.ts'.

Point two was the direct reason for my issue, point one just made it really confusing when trying to debug.