装饰器不支持函数调用,而 ng build --prod (AOT)

Posted

技术标签:

【中文标题】装饰器不支持函数调用,而 ng build --prod (AOT)【英文标题】:Function calls are not supported in decorators while ng build --prod (AOT) 【发布时间】:2018-09-05 15:54:33 【问题描述】:

问题类型:错误/问题

说明

我正在使用 ng-packagr lib 将我的库编译为 js。我已经编译了所有内容,没有任何问题,但是当我想使用 ng build --prod(启用 AOT)来使用我的库时,我收到了错误:

ERROR in Error during template compile of 'AppModule' Function calls are not supported in decorators but 'BsDropdownModule' was called.

当我删除 .forRoot 方法时,出现错误:

ERROR in : Unexpected value 'BsDropdownModule in /home/sf/Desktop/Developerka/kompilacja/final/sample-repo/node_modules/angular-library-name/free/dropdown/dropdown.module.d.ts' imported by the module 'AppModule in /home/sf/Desktop/Developerka/kompilacja/final/sample-repo/src/app/app.module.ts'. Please add a @NgModule annotation

请注意,ng --prod --aot=false 没有产生任何错误。

如何复制:

下载repo:https://github.com/Bloodcast69/aot-error,输入 npm install ng build --prod.

预期行为

想要使用 AOT 构建而不会出现错误(我需要它与 Angular Universal 兼容) 版本信息

ng-packagr: 2.4.1 @angular/*: 5.2.9 typescript: 2.5.3 rxjs: 5.5.6 node: 8.1.0 npm/yarn: npm: 5.6.0

文件:

app.module.ts:

import  BsDropdownModule  from 'angular-library-name';
import  BrowserModule  from '@angular/platform-browser';
import  NgModule  from '@angular/core';



import  AppComponent  from './app.component';


@NgModule(
  declarations: [
    AppComponent
  ],
  imports: [
    BsDropdownModule.forRoot(),
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
)
export class AppModule  

dropdown.module.d.ts:

import  ModuleWithProviders  from '@angular/core';
export declare class BsDropdownModule 
    static forRoot(config?: any): ModuleWithProviders;

dropdown.module.ts(编译成 JS 之前):

import  ModuleWithProviders, NgModule  from '@angular/core';
import  ComponentLoaderFactory  from '../utils/component-loader/index';

import  PositioningService  from '../utils/positioning/index';
import  BsDropdownContainerComponent  from './dropdown-container.component';
import  BsDropdownMenuDirective  from './dropdown-menu.directive';
import  BsDropdownToggleDirective  from './dropdown-toggle.directive';
import  BsDropdownConfig  from './dropdown.config';

import  BsDropdownDirective  from './dropdown.directive';
import  BsDropdownState  from './dropdown.state';

@NgModule(
  declarations: [
  BsDropdownMenuDirective,
  BsDropdownToggleDirective,
  BsDropdownContainerComponent,
  BsDropdownDirective
  ],
  exports: [
  BsDropdownMenuDirective,
  BsDropdownToggleDirective,
  BsDropdownDirective
  ],
  entryComponents: [BsDropdownContainerComponent]
)
export class BsDropdownModule 
  public static forRoot(config?: any): ModuleWithProviders 
    return 
      ngModule: BsDropdownModule, providers: [
      ComponentLoaderFactory,
      PositioningService,
      BsDropdownState,
      provide: BsDropdownConfig, useValue: config ? config : autoClose: true
      ]
    ;
  ;

注意 我已经阅读了整个互联网以找到对我有帮助的东西,但没有任何成功。我已经检查了这些主题:

FeatureModule fails during an AOT build when static forRoot has arguments

https://github.com/angular/angular/issues/14707

如果缺少一些需要的信息,请告诉我,我会提供。

谢谢, 血铸69

【问题讨论】:

BsDropdownModule 在 node_modules/angular-library-name/free/dropdown 你必须 npm install 才能看到它。这个模块是编译成js之后的。 对不起,我的错。请立即尝试,我已添加 angular-library-name-5.2.3.tgz 文件并将其添加到依赖项中。下载新的 repo 并输入 npm i @yurzui 你能用更多的词来形容吗? 好的,我会测试它,让你知道它是否有效。 这是另一回事。我必须为某些提供商指出确切的路径。例如,不是从 './services' 导入 service ,而是从 './services/sample.service 导入 service 。不过感谢您的帮助! 【参考方案1】:

这是 AOT 的问题:forRoot 函数需要在编译时执行。在更新版本的 Angular 上,它应该按原样工作,否则你可能会幸运地使用 tsconfig.app.json。检查这个相关问题:Angular 6 Prod Function calls are not supported in decorators but '..Module' was called

【讨论】:

【参考方案2】:

您的 forRoot 方法应返回 ModuleWithProviders 并用 @NgModule 注释

  import  ModuleWithProviders, NgModule  from '@angular/core';

    @NgModule(
        declarations: [],
        imports: [],
        providers: [],

      )
    export class BsDropdownModule 
       // constructor(parentModule: BsDropdownModule);
        //  static forRoot(config?: any): ModuleWithProviders;
        static forRoot(config?: any): ModuleWithProviders 

            return 
                ngModule: BsDropdownModule,
                providers: [
                ]
            
        
    

所以,你应该在app.module 中导入dropdown.module 而不是声明文件dropdown.module.d.ts

import  BsDropdownModule  from './dropdown.module';


@NgModule(
  declarations: [
    AppComponent
  ],
  imports: [
    BsDropdownModule.forRoot(),
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
)
export class AppModule  

我使用AOT 构建进行了测试。没有错误

【讨论】:

您输入的代码包含在尚未编译为 .js 的模块中。编译后的模块只包含我粘贴的代码,并且由于某种原因,该代码在编译后不起作用 - 它会抛出我在上面粘贴的错误。请检查我在上面发布的 dropdown.module.ts 代码。 import BsDropdownModule from 'angular-library-name'; 是 dropdown.module.ts 吗? angular-library-name 从 'angular-library-name' 导入 BsDropdownModule ;编译成js模块。将此模块导入我的 app.module 时,我无法在 AOT 时对其调用 forRoot() 方法。如果您有不清楚的地方,也许可以尝试下载我的 repo 并查看代码?【参考方案3】:

我也面临同样的问题,我能够将其缩小到 ng-packagr。 我从库中提取了我的模块并在单独的应用程序中进行了测试,我没有遇到任何 AOT 错误。仅当我将模块打包到库中时才会出现此错误

我正在使用 Angular 6.1.8 和 ng-packagr 4.2.0

【讨论】:

这并不能解决问题。我知道您没有获得评论特权,但这无助于解决问题

以上是关于装饰器不支持函数调用,而 ng build --prod (AOT)的主要内容,如果未能解决你的问题,请参考以下文章

装饰器

python之“装饰器”

类装饰器不绑定自我

Python中的“ @”(@)符号有啥作用?

js支持装饰器

Python @property 装饰器不起作用