在构建用于生产的 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 {}
因此,根据其中一位主要贡献者的说法,您的问题的解决方案将类似于:
// 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 {}
因此,在该功能未实现之前,我没有更好的解决方案来解决您的问题。
所选答案不再有效。对于 Angular CLI 6,正如建议,我们必须将 dev 和 prod 视为共享相同代码库的单独项目。
解决方案总结
详情
复制 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
条件构建示例(Webpack):
export default class XMockService {
...
}
if(environment.mock)
{
let XMockService = System.import('./x.mock.service');
importedModules.push(
{provide: XService, useClass: XMockService}
);
}
它将创建额外的块,如
0.chunk.js
。
只需在同一目录中创建模拟模块的空版本即可。
你的模拟.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 中.