Angular-cli: Angular2 AOT compilation - "Cannot determine the module for class (... many components which are unused)"

Created on 19 Dec 2016  路  9Comments  路  Source: angular/angular-cli

OS?

Cross platform, Testing on Windows 10 now.

Versions.

node v6.3.0

Repro steps.

  1. Create some components
  2. reference one of them in an appModule
  3. bootstrap the module with one component
  4. build with @ngtool/webpack loader
  5. see errors for other unused components

The log given by the failure.

Cannot determine the module for class (....) for each component we don't use.

at analyzeNgModules (C:\Repos\Project\PROJECT\client\node_modules\@angular\compiler\bundles\compiler.umd.js:13079:17)
    at OfflineCompiler.compileModules (C:\Repos\Project\PROJECT\client\node_modules\@angular\compiler\bundles\compiler.umd.js:13115:20)
    at CodeGenerator.codegen (C:\Repos\Project\PROJECT\client\node_modules\@angular\compiler-cli\src\codegen.js:58:30)
    at AotPlugin._make (C:\Repos\Project\PROJECT\client\node_modules\@ngtools\webpack\src\plugin.js:187:43)
    at Compiler.<anonymous> (C:\Repos\Project\PROJECT\client\node_modules\@ngtools\webpack\src\plugin.js:151:75)
    at Compiler.applyPluginsParallel (C:\Repos\Project\PROJECT\client\node_modules\tapable\lib\Tapable.js:193:14)
    at C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:468:8
    at Compiler.applyPluginsAsyncSeries (C:\Repos\Project\PROJECT\client\node_modules\tapable\lib\Tapable.js:95:46)
    at Compiler.compile (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:461:7)
    at C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:47:17
    at next (C:\Repos\Project\PROJECT\client\node_modules\tapable\lib\Tapable.js:102:11)
    at Compiler.<anonymous> (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\CachePlugin.js:31:4)

    at next (C:\Repos\Project\PROJECT\client\node_modules\tapable\lib\Tapable.js:104:14)
    at Compiler.<anonymous> (C:\Repos\Project\PROJECT\client\node_modules\browser-sync-webpack-plugin\index.js:26:5)
    at Compiler.applyPluginsAsyncSeries (C:\Repos\Project\PROJECT\client\node_modules\tapable\lib\Tapable.js:106:13)
    at Watching._go (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:45:16)
    at Watching.<anonymous> (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:36:8)
    at Compiler.readRecords (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:371:10)
    at new Watching (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:33:16)
    at Compiler.watch (C:\Repos\Project\PROJECT\client\node_modules\webpack\lib\Compiler.js:205:17)
    at processOptions (C:\Repos\Project\PROJECT\client\node_modules\webpack\bin\webpack.js:332:12)
    at Object.<anonymous> (C:\Repos\Project\PROJECT\client\node_modules\webpack\bin\webpack.js:339:1)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:458:32)
    at tryModuleLoad (module.js:417:12)
    at Function.Module._load (module.js:409:3)
    at Module.runMain (module.js:575:10)
    at run (bootstrap_node.js:352:7)
    at startup (bootstrap_node.js:144:9)

Mention any other details that might be useful.

We have a src directory with modules and our app components. However, we use a shared npm module to provide common components, pipes, directives, etc between partner apps. This works fine for JIT, but seems to want a module for every component in the shared npm module too, even if we don't need it for this partner.

Most helpful comment

I'm getting the same problem on the lastest cli (beta.22-1).

I have a router-stubs.ts file in my folder /testing, which holds a RouterLinkDirectiveStub @Directive, which is basically a file to hold common testing stub classes. It is only imported in spec files, so I don't expect it to have an impact on building.

> ng build --aot

10% building modules 3/3 modules 0 activeCannot determine the module for class RouterLinkDirectiveStub in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.ts!

Cannot determine the module for class RouterOutletStubComponent in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.ts!
Error: Cannot determine the module for class RouterLinkDirectiveStub in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.t
s!
Cannot determine the module for class RouterOutletStubComponent in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.ts!
    at analyzeAndValidateNgModules (/home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/node_modules/@angular/compiler/b
undles/compiler.umd.js:12707:17)
    at OfflineCompiler.compileModules (/home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/node_modules/@angular/compile
r/bundles/compiler.umd.js:12775:20)
    at CodeGenerator.codegen (/home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/node_modules/@angular/compiler-cli/src
/codegen.js:58:30)
    at /home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/src/plugin.js:210:73
    at process._tickCallback (internal/process/next_tick.js:103:7)

Adding and removing -prod doesn't change the end result.

All 9 comments

The error points to a line in @angular/compiler/bundles/compiler-umd.js which looks like this:

      var symbolsMissingModule = programPipesOrDirectives.filter(function (s) { return !ngModuleByPipeOrDirective.has(s); });
      if (symbolsMissingModule.length) {
          var messages = symbolsMissingModule.map(function (s) { return ("Cannot determine the module for class " + s.name + " in " + s.filePath + "!"); });
          throw new Error(messages.join('\n'));
      }

I tried to edit these lines to see if it would be possible to add an IgnoreUnusedComponents flag or something by hardcoding the lines to this:

  programPipesOrDirectives = programPipesOrDirectives.filter(function (s) { return ModuleByPipeOrDirective.has(s); });

which should just continue, using only components which do have a declared module. However, This simply blows up later down the line, somehow recognizing local code as "external module which cannot be named"

This is not really an Angular CLI issue, but an Angular one.
Angular AOT compilation requires that every component/directive is declared in an ngModule. There's no workaround. I don't understand why you can't put these shared components in an ngModule, that is how the ng2 architecture works.

@rolandoldengarm because they don't all belong in the same module. We have an npm module we have created that is essentially a library of generic (with respect to our partner implementations) components, pipes, and directives, to be included as needed. Our base app uses all of them, and thus has no issue with AoT. However, many of our partners require a custom component/pipe/directive in place of the base. Or more common, they DON'T require a large number of our components at all.

My understanding of webpack was that if a file is not in the require chain, it is removed from consideration. But if that were the case, it would not blow up at these components (which are entirely unused) lacking a module.

If this is really an ngc issue, I will open up an issue with them, but I figured the webpack side of this should be weeding out unused files, so I opened this one here.

@swimmadude66 ah I see.. Hmm, does it make a difference if you try a production build?

We only do AoT with the production flag enabled, so that's all I've tried.

I'm getting the same problem on the lastest cli (beta.22-1).

I have a router-stubs.ts file in my folder /testing, which holds a RouterLinkDirectiveStub @Directive, which is basically a file to hold common testing stub classes. It is only imported in spec files, so I don't expect it to have an impact on building.

> ng build --aot

10% building modules 3/3 modules 0 activeCannot determine the module for class RouterLinkDirectiveStub in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.ts!

Cannot determine the module for class RouterOutletStubComponent in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.ts!
Error: Cannot determine the module for class RouterLinkDirectiveStub in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.t
s!
Cannot determine the module for class RouterOutletStubComponent in /home/ciesielskico/Documents/webapp/src/testing/router-stubs.ts!
    at analyzeAndValidateNgModules (/home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/node_modules/@angular/compiler/b
undles/compiler.umd.js:12707:17)
    at OfflineCompiler.compileModules (/home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/node_modules/@angular/compile
r/bundles/compiler.umd.js:12775:20)
    at CodeGenerator.codegen (/home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/node_modules/@angular/compiler-cli/src
/codegen.js:58:30)
    at /home/ciesielskico/Documents/webapp/node_modules/@ngtools/webpack/src/plugin.js:210:73
    at process._tickCallback (internal/process/next_tick.js:103:7)

Adding and removing -prod doesn't change the end result.

well damn. That means even without the webpack plugin, the ngc is aware of your entire working directory.
Guess I'll go open a similar issue with the angular team. Will reference here once I do.

Would still be nice if the @ngtools/webpack plugin could maybe mask files not in the require chain, since it's already aware of them. I think the best bet in the meantime will be a loader which moves all files in the require chain to a new workspace and runs the compiler there, but that's a REALLY ugly solution....

EDIT: angular/angular ticket: https://github.com/angular/angular/issues/13590

angular/angular#13590 seems better to track this, it's not a CLI issue per se.

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings