带有构建优化器的 AOT 和 JIT

AOT and JIT with build-optimizer

我正在遵循使用 JitCompilerFactory 加载 运行time 编译器和自定义装饰器的解决方案 here 以保留组件和模块元数据。但是使用 angular-cli --build-optimizer 标志我得到:

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是我的最小复制,运行ng serve --aot --build-optimizer。作为控件 ng serve --aot 有效。

如果您使用选项 --build-optimizer,那么 @angular-devkit/build-optimizer/webpack-loader 加载程序将添加到 webpack 加载程序列表中。

@angular-devkit/build-optimizer/webpack-loader 从不属于 platformWhitelist (source) 的类型中删除 ctorParameters 定义:

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

我认为这是正确的行为。

要解决此问题,您可以在 JitCompilerFactory 之前手动初始化 ctorParameters 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)]];
}

这似乎是有风险的,因为 编译器会发生内部变化。它适用于 @angular/compiler@4.4.5,但可能不适用于其他版本。