2

I am following the solution here of using the JitCompilerFactory to load the runtime compiler and custom decorators to preserve the component and module metadata. But with the angular-cli --build-optimizer flag I get:

ERROR Error: Cannot resolve all parameters for 'Parser'(?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'Parser' is decorated with Injectable.

Here is my minimal reproduction, run ng serve --aot --build-optimizer. As a control ng serve --aot works.

Wilhelmina Lohan
  • 2,803
  • 2
  • 29
  • 58

1 Answers1

0

If you use option --build-optimizer then @angular-devkit/build-optimizer/webpack-loader loader is added to webpack loaders list.

@angular-devkit/build-optimizer/webpack-loader removes ctorParameters definitions from types that is not part of platformWhitelist (source):

const platformWhitelist = [
  'PlatformRef_',
  'TestabilityRegistry',
  'Console',
  'BrowserPlatformLocation',
];

I think that's correct behavior.

To work around it you could initialize ctorParameters manually before JitCompilerFactory is created:

import { 
  Compiler, ɵConsole as Console,
  Optional, Inject, Injector, 
  PACKAGE_ROOT_URL 
} from '@angular/core';

import {
  JitCompilerFactory,
  TemplateParser, CompilerConfig, CompileReflector,
  ElementSchemaRegistry, I18NHtmlParser, TEMPLATE_TRANSFORMS, DirectiveNormalizer,
  ResourceLoader, UrlResolver, HtmlParser, CompileMetadataResolver, NgModuleResolver,
  DirectiveResolver, SummaryResolver, PipeResolver, StaticSymbolCache, 
  ERROR_COLLECTOR_TOKEN,
  StyleCompiler, ViewCompiler, NgModuleCompiler, JitCompiler
} from '@angular/compiler';

import * as compiler from '@angular/compiler';

export function compilerFactory() {
  restoreDecorators();

  return new JitCompilerFactory([{ useDebug: false, useJit: true }]).createCompiler();
}

function restoreDecorators() {
  (compiler.Parser as any).parameters = [compiler.Lexer];
  (TemplateParser as any).parameters = [
    CompilerConfig, CompileReflector, compiler.Parser, ElementSchemaRegistry,
    I18NHtmlParser, Console, [new Optional(), new Inject(TEMPLATE_TRANSFORMS)]
  ];
  (DirectiveNormalizer as any).parameters = [
    ResourceLoader, UrlResolver,
    HtmlParser, CompilerConfig
  ];
  (CompileMetadataResolver as any).parameters = [
    CompilerConfig, NgModuleResolver, DirectiveResolver, PipeResolver, SummaryResolver,
    ElementSchemaRegistry,
    DirectiveNormalizer, Console,
    [new Optional(), StaticSymbolCache],
    CompileReflector,
    [new Optional(), new Inject(ERROR_COLLECTOR_TOKEN)]
  ];
  (StyleCompiler as any).parameters = [UrlResolver];
  (ViewCompiler as any).parameters = [CompileReflector];
  (NgModuleCompiler as any).parameters = [CompileReflector];
  (NgModuleResolver as any).parameters = [CompileReflector];
  (DirectiveResolver as any).parameters = [CompileReflector];
  (PipeResolver as any).parameters = [CompileReflector];

  (JitCompiler as any).parameters = [
    Injector,
    CompileMetadataResolver,
    TemplateParser,
    StyleCompiler,
    ViewCompiler,
    NgModuleCompiler,
    SummaryResolver,
    CompilerConfig,
    Console
  ];
  (UrlResolver as any).parameters = [[new Inject(PACKAGE_ROOT_URL)]];
}

And it seems to be risky as compiler is subject to internal changes. It works for @angular/compiler@4.4.5 but may not work for other releases.

yurzui
  • 205,937
  • 32
  • 433
  • 399
  • I don't know what `ctorParameters` are but from context I'm gathering that it is how the DI knows what to inject to service's (and ect) constructors. Could it be as simple as adding `Compiler` to the `platformWhitelist` if you forked https://github.com/angular/devkit or made a feature request? – Wilhelmina Lohan Oct 16 '17 at 17:18
  • We shouldn't do it. – yurzui Oct 16 '17 at 17:20