如何不在Angular2生产包中包含模拟服务

时间:2016-12-29 22:51:19

标签: angular mocking angular-cli

在构建角度2应用程序进行制作时,我们使用

ng build --prod --w --aot 

但是我们的模拟服务也因为我们有

而被捆绑和缩小
import {XMockService} from "./xxx-mock.service";

这可以防止树摇动掉掉未使用的服务。这是我们简化的app.module.ts,它在environment.mock = true时有条件地延迟加载模拟服务

我想这是一个常见的场景,但我找不到任何答案。

app.module.ts:

import {BrowserModule} from "@angular/platform-browser";
import {NgModule} from "@angular/core";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {environment} from "../environments/environment";
import {XService} from "./xxx.service";
import {XMockService} from "./xxx-mock.service";

let importedModules: Array<any> = [
  XService
];

if (environment.mock) {
  importedModules.push(
    {provide: XService, useClass: XMockService}
  );
} else {
  importedModules.push(
    XService
  );
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: importedModules,
  bootstrap: [AppComponent]
})

export class AppModule {}

3 个答案:

答案 0 :(得分:7)

所以根据main contributors中的一个,您的问题的解决方案将是:

// main.ts
import './polyfills.ts';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment, AppModule } from './environments/environment';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppModule);

// environments/environment.ts
export { DevModule as AppModule } from '../app/dev.module';

export const environment = {
  production: false
};
// environments/environment.prod.ts
export { ProdModule as AppModule } from '../app/prod.module';

export const environment = {
  production: true
};

所以它与我之前的答案非常相似,不同之处在于您将使用不同的环境文件,而不是使用不同的主文件。

上一个答案

最近opened an issue on Angular-cli,请求了一项功能,可以让您这样做。怎么样?通过切换您的webpack入口点。现在Angular-cli总是使用相同的入口点src/main.ts,这个功能背后的想法是你可以指定一个不同的入口点,所以你会有类似src/main.dev.ts的东西:

import './polyfills.ts';

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
import { AppDevModule } from './app/app.dev.module';

if (environment.production) {
  enableProdMode();
}

platformBrowserDynamic().bootstrapModule(AppDevModule);

然后你会在AppDevModule上导入你的模拟:

import {BrowserModule} from "@angular/platform-browser";
import {NgModule} from "@angular/core";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {environment} from "../environments/environment";
import {XMockService} from "./xxx-mock.service";

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [XMockService],
  bootstrap: [AppComponent]
})

export class AppDevModule {}

以这种方式做事的唯一不利方面是,您必须保持AppModuleAppDevModule同步。

您可以通过创建第三个文件来解决这个问题,例如AppImportsModule

import {BrowserModule} from "@angular/platform-browser";
import {FormsModule} from "@angular/forms";
import {HttpModule} from "@angular/http";
import {AppComponent} from "./app.component";
import {environment} from "../environments/environment";

export {AppComponent} //we also export this for simplicity

export const declarations = [
  AppComponent
];

export const imports = [
  BrowserModule,
  FormsModule,
  HttpModule
];

然后在您的AppModule.tsAppDevModule.ts上,您只需要导入您的提供商:

import {NgModule} from "@angular/core";
import {declarations, imports, AppComponent} from "./app.imports.module";
import {XMockService} from "./xxx-mock.service";

@NgModule({
  declarations, // with es6 this is the same as "declarations: declarations"
  imports, //same as above
  providers: [XMockService],
  bootstrap: [AppComponent]
})

export class AppDevModule {}

因此,在该功能未实施之前,我没有更好的解决方案来解决您的问题。

答案 1 :(得分:2)

所选答案不再有效。对于Angular CLI 6,recommended,我们必须将dev&prod视为共享相同代码库的单独项目。

解决方案摘要

  • 每个环境都有单独的项目。 (就像angular.json中的几行一样简单)
  • 具有与每个单独的main.ts文件的env数量一样多的AppModule
  • 每个环境都有单独的tsconfig文件
  • 通过angular.json告诉有关更改的信息

详细信息

复制AppModule并将其命名为DevModule。 (DevModule用于开发,AppModule用于产品)。 DevModule将是带有模拟服务的那个。

每个都有单独的main.ts文件。对prod说prod-main.ts,对dev说dev-main.ts。唯一的区别是prod-main加载AppModule,而dev-main加载DevModule。

将tsconfig.app.json文件复制到tsconfig.prod.json和tsconfig.dev.json中。在tsconfig.prod.json的排除部分中,键入“ dev-main.ts”,“ app / dev-module.ts”,“ ** / mock-*。ts”。还要输入其他开发模块(加载模拟模块的模块)。

为开发人员重复。对于ts​​config.dev.json,排除prod-main.ts,app / app-module.ts。必要时也对tsconfig.spec.json文件进行相关更改(不包括类似内容)。

更新angular.json文件以反映新的tsconfig文件。

// angular.json. Only the relevant parts are given below.
// Essentially, separate tsconfig files for 2 projects - dev & prod
{
  "newProjectRoot": "projects",
  "projects": {
    "my-prod-proj": {
      "architect": {
        "build": {
          "options": {
            "main": "src/main-prod.ts",
            "tsConfig": "src/tsconfig.app.json",
          },
        },
        "test": {
          "options": {
            "tsConfig": "src/tsconfig.prod.spec.json",
          }
        },
        "lint": {
          "options": {
            "tsConfig": [
              "src/tsconfig.prod.json",
              "src/tsconfig.prod.spec.json"
            ],
          }
        }
      }
    },
    "my-dev-proj": {
      "architect": {
        "build": {
          "options": {
            "main": "src/dev-main.ts",
            "tsConfig": "src/tsconfig.dev.json",
          }
        },
        "test": {
          "options": {
            "tsConfig": "src/tsconfig.dev.spec.json",
          }
        },
        "lint": {
          "options": {
            "tsConfig": [
              "src/tsconfig.dev.json",
              "src/tsconfig.dev.spec.json"
            ],
          }
        }
      }
    },
  },
  "defaultProject": "my-prod-proj",
}

按名称运行项目

ng serve my-dev-proj // dev with mocks
ng serve             // prod (set as default in angular.json)
same goes for the build command

答案 2 :(得分:0)

条件构建示例(Webpack):

export default class XMockService {

  ...

}

if(environment.mock)
{
    let XMockService = System.import('./x.mock.service');
    importedModules.push(
       {provide: XService, useClass: XMockService}
    );
}

它会创建像0.chunk.js这样的额外块。