Skip to content

Instantly share code, notes, and snippets.

@gund
Last active July 4, 2018 18:27
Show Gist options
  • Save gund/fa244bfef5024ebe2aba72d31d565cb0 to your computer and use it in GitHub Desktop.
Save gund/fa244bfef5024ebe2aba72d31d565cb0 to your computer and use it in GitHub Desktop.
Webpack 2 beta circular dependencies trouble

So consider we have Logger class. And also we have a LoggerInContext class which extends Logger. And Logger has factory method to create new LoggerInContext instances.

// logger.ts

import { LoggerInContext } from './logger-in-context';

export class Logger {
  // Some methods like log()...
  
  getInContext(context) {
    return new LoggerInContext(context);
  }
}
// logger-in-context.ts

import { Logger } from './logger';

export class LoggerInContext extends Logger {
  constructor(public context) {
    super();
  }
  
  // Here we can override some behavior
}

So as we will try to import logger.ts into our application Webpack will then run into file logger-in-context.ts but at that time Logger will be undefined so our extend will fail and stack trace will look something like this (TS compiler is doing his job here as well):

Uncaught TypeError: Cannot read property 'prototype' of undefined
    at __extendsFn (index.js:15)
    at eval (logger-in-context.ts:4)
    at eval (logger-in-context.ts:50)
    at Object../src/app/services/logger/logger-in-context.ts (index.js:718)
    at __webpack_require__ (index.js:48)
    at eval (logger.service.ts:5)
    at Object../src/app/services/logger/logger.service.ts (index.js:726)
    at __webpack_require__ (index.js:48)
    at eval (index.ts:5)
    at Object../src/app/services/logger/index.ts (index.js:702)
    at __webpack_require__ (index.js:48)
    at eval (auth-interceptor.service.ts:7)
    at Object../src/app/services/sso/auth-interceptor/auth-interceptor.service.ts (index.js:742)
    at __webpack_require__ (index.js:48)
    at eval (index.ts:5)

And in generated code error comes from here (simplified a bit):

var logger_1 = __webpack_require__("./src/logger.ts");
// ...
__extends(LoggerInContext, logger_1.Logger); // <--- This is yet undefined
@Jessidhia
Copy link

Jessidhia commented Dec 27, 2016

@trusktr IIUC, export {Logger} should avoid your issue with let. You can even do export { Logger as default } if you want to make it the default export.

The problem with export default Logger is that, as export default is exporting an expression result (the current value of Logger), and export are evaluated before other code, Logger is being read before it is defined (i.e. while it is in TDZ). That actually probably should be an error even in native ES modules.

@Choleriker
Copy link

Guys, there is another simple solution for this. I have 2 modules which are somehow deep in the structure using each other. I ran into the same problem with circular dependencies with webpack and angular 2. I simply changed the way of how the one module is declared:

....

@NgModule({
    imports: [
        CommonModule,
        FormsModule,
        require('../navigation/navigation.module')
    ],
    declarations: COMPONENTS,
    exports: COMPONENTS
})
class DppIncludeModule {
    static forRoot(): ModuleWithProviders {
        return {
            ngModule: DppIncludeModule
        };
    }
}

export = DppIncludeModule;

When I now using the imports statement on ngModule attribute I simply use:

@NgModule({
    imports: [
        CommonModule,
        ServicesModule.forRoot(),
        NouisliderModule,
        FormsModule,
        ChartModule,
        DppAccordeonModule,
        PipesModule,
        require('../../../unbranded/include/include.module')
    ],
....

With this all problems are away.

@gund
Copy link
Author

gund commented Aug 16, 2017

@Choleriker I believe your solution will most likely break Angular's AOT compatibility

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment