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

问题描述 投票:0回答:4

在构建用于生产的 Angular 2 应用程序时,我们使用

ng build --prod --w --aot 

但是我们的模拟服务也被捆绑和缩小,可能是因为我们有

import {XMockService} from "./xxx-mock.service";

这可以防止 Tree Shaking 丢弃未使用的服务。这是我们简化的 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 {}
angular mocking angular-cli
4个回答
8
投票

因此,根据其中一位主要贡献者的说法,您的问题的解决方案将类似于:

// 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
};

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

之前的回答

最近在 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 {}

以这种方式做事的唯一缺点是,您必须保持

AppModule
AppDevModule
同步。

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

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.ts
AppDevModule.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 {}

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


3
投票

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

解决方案总结

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

详情

复制 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”。也输入其他开发模块(加载模拟的模块)。

对开发人员重复此操作。对于 tsconfig.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

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


0
投票

只需在同一目录中创建模拟模块的空版本即可。

你的模拟.module.empty.ts

import { NgModule } from "@angular/core";

@NgModule({ })
export class YourMockModule {
}

并将其添加到所有部署环境的 angular.json 中,以替换原始的模拟模块,以便在除 localhost 之外的所有环境中排除所有测试数据和代码:

{
  "replace": "path-to/your-mock.module.ts",
  "with": "path-to/your-mock.module.empty.ts"
}

位于“projects”/“{ your-project-name }”/“architect”/“build”/“configurations”/“{ Production-or-other-environment }”/“fileReplacements”树中的 angular.json 中.

© www.soinside.com 2019 - 2024. All rights reserved.