Angular2 AoT - 在组件中设置module.id时未定义module.id

时间:2016-09-23 14:09:03

标签: angular angular2-aot

我正面临Angular2 AoT的挑战,因为我被困住了,任何帮助对我来说都是一个很大的帮助。

我有一个简单的hello world应用程序,它有main.js,home.module.ts,home.component.ts,home.component.html和home.service.ts。这个代码在没有AoT的情况下使用Angular2很有效。

在我按照cookbook中的angular.io步骤精确执行AoT和Rollup后,我收到错误:“未捕获的ReferenceError:模块未定义”,我不知道为什么会发生这种情况。

My Home.Component.ts标记如下:

@Component({
    selector: 'rf-home',
    moduleId: module.id,   // i m setting this module.id so that I can use relative template paths in my code. Helps in Dev env.
    templateUrl: 'Home.component.html',
    providers: [HomeService]
})

有人在那里,请帮忙!

2 个答案:

答案 0 :(得分:3)

更新:2016年10月22日

从Angular 2.1开始,文档的AOT部分(https://angular.io/docs/ts/latest/cookbook/aot-compiler.html)有一个更简单的方法。

<script>window.module = 'aot';</script>

这一行放在aot build的index.html文件中。

TL;博士

我正在使用的修复是添加一个自定义提供程序,用于检查模块对象是否在浏览器中可用,如果找不到则将其添加到全局范围。

  1. 创建以下类:rollup-module.provider.ts

    export function RollupModuleProvider(params: any) {
        return function (target: any) {
            // Setup the 'module' variable globally. The rollup javascript has its own module system, but there is still a
            // reference to the Commonjs module.id in the code, so setup a module object to allow that code to execute
            // without throwing an exception
            try {
                // In dev mode with commonjs the following line will execute without a problem
                // In AoT mode with rollup the following line will trigger an exception that will be
                // caught and handled to allow the AoT build to run without issue
                let testIfRunningWithCommonJSandModuleIsAvailable = module.id;
            } catch (e) {
                // Declare Module for rollup based production builds.
                // When running dev builds CommonJS automatically provides the module definition
                console.log("Defining Module");
                var globalScope: any;
                if (typeof window === 'undefined') {
                    globalScope = global;
                }
                else {
                    globalScope = window;
                }
                globalScope.module = "test";
                try {
                    let moduleShouldBeAvailable = module;
                }
                catch (e) {
                    // Our attempt to register module failed so we are not in an unrecoverable error state.
                    console.error("Module not defined");
                }
            }
        }
    }
    
  2. 在app.component.ts中添加以下代码段。请注意,app.component.ts应该是&#34; bootstrap&#34;中的类。 app.module.ts文件中的声明。

    import {RollupModuleProvider} from "./rollup-module.provider";
    
    @RollupModuleProvider({})
    
  3. 详细

    为了完整性,这是下面的完整app.component.ts。注意我内联此组件中的模板以进一步简化构建。对于应用程序中的其他组件&#39;模板&#39;可用于内联html或&#39; templateUrl&#39;可以用来将html放在一个单独的文件中。对于除主app.component.ts之外的所有组件,此选择可以基于个人/项目偏好。

        import { Component } from '@angular/core';
    
        import './rxjs-operators';
        import {ModalService} from "./shared/modal.service";
        import {RollupModuleProvider} from "./rollup-module.provider";
    
        @RollupModuleProvider({})
        @Component({
            selector: 'myapp',
            /* For only the top level component inline the template which simplifies the build process. By in-lining the
             * template we don't need to setup the "module: module.id" on the Component decorator. We use the RollupModuleProvider
             * to setup the module variable when running in a ngc/rollup build. In a dev build the CommonJs module system is used
             * so module.id is available. In a ngc/rollup build the module does not need to be set on the component so it can be
             * set to a valid value and then is essentially ignored.
             */
            template:
                `<div [class.modalDisplayed]="modalService.isModalDisplayed()"></div>
                    <nav-header></nav-header>
                    <div class="container-fluid">
                    <router-outlet> </router-outlet>
                </div>`
        })
    
        export class AppComponent {
            constructor (public modalService: ModalService) {
            }
        }
    

    这是完整的app.module.ts。

        import {NgModule}      from '@angular/core';
        import { BrowserModule } from '@angular/platform-browser';
        import { HttpModule } from '@angular/http';
    
        import { AppComponent }  from './app.component';
        import { routing } from './app.routing';
    
        import { Logger } from './logger.service';
        import { HttpClient } from './http.client.service';
        import {WindowSize} from './window-size.service';
        import {ModalService} from "./shared/modal.service";
        import {SharedModule} from "./shared/shared.module";
    
        @NgModule({
            imports: [BrowserModule, HttpModule, routing, SharedModule],
            declarations: [AppComponent],
            providers: [ Logger, HttpClient, WindowSize, ModalService ],
            bootstrap: [ AppComponent ]
        })
    
        export class AppModule { }
    

    详细说明

    作为解决方案的一部分,我希望能够将moduleId定义留在代码中,以便我可以继续运行tsc并使用commonjs进行开发。 AoT不需要moduleId来运行。 UncaughtReferenceError出现在具有AoT构建的浏览器中,因为浏览器没有&#34; module&#34;在全局范围内可用(通常是JavaScript窗口对象)。在开发模式下,commonjs设置模块,因此没有问题。

    由于AoT不需要moduleId,因此修复是在AoT模式下运行时在浏览器中简单设置模块对象。除了被定义以避免抛出引用错误之外,模块对象不必做任何事情。

    设置全局范围的代码来自角度2代码库,只是稍微修改了这个用法。

答案 1 :(得分:1)

修复此错误的另一种方法:

  1. 删除moduleId:module.id
  2. templateUrl:'Home.component.html'替换为 的模板: 要求( '到字符串!./ Home.component.html.html')

    @Component({
         选择器:'rf-home',
        template:require('to-string!./ Home.component.html.html'),
        提供者:[HomeService]
    })