基础架构
对于网络应用程序,前端越来越大,我们的网络应用程序中 90%是前端代码.
随着时间的推移,Web 应用也会发生变化,开发技术和框架也是如此, 这需要支持允许不同的前端框架共存、共用、共生, 前端微服务化应运而生.
-
获取微服务基础工程
下载 github 微服务 Master 分支基础工程 ZIP 包,然后初始化 git 和安装依赖.
-
依赖
a. angular 版本: 6.1
b. 使用 ng-cosmos-ui 组件库,water-service处理后端数据
c. 使用 water-utils 处理国际化和多主题切换
-
目录说明
├── [说明] README.md
├── [ng配置] angular.json
├── [webpack配置] config
├── [微服务部署] deploy
├── [打包输出] dist
├── [测试] e2e
├── [依赖包] node_modules
├── [依赖锁定] package-lock.json
├── [依赖配置] package.json
├── [代码检查] sonar-project.properties
├── [开发目录] src
├── [测试] test.json
├── [ts配置] tsconfig.json
├── [ts检查] tslint.json
└── [webpack基础配置] webpack.config.js
- 启动工程
//安装依赖
$ npm i
//启动开发服务
$ npm start
- 在根 Module 中定义 需要引入@angular/elements,elements-zone-strategy,示例:
/**
* soa-demo
* https://github.com/lamphc/ng-microservice
*/
import { BrowserModule } from "@angular/platform-browser";
import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
import { NgModule, Injector } from "@angular/core";
import { FormsModule } from "@angular/forms";
import { createCustomElement } from "@angular/elements";
import { ElementZoneStrategyFactory } from "elements-zone-strategy";
import { NgZorroAntdModule, NZ_I18N, zh_CN } from "ng-cosmos-ui";
import { CenterModule } from "./center/center.module";
import { AppComponent } from "./app.component";
// 配置 angular i18n
import { registerLocaleData } from "@angular/common";
import zh from "@angular/common/locales/zh";
registerLocaleData(zh);
// 配置 water-utils i18n for soa
import {
TranslateModule,
TranslateLoader,
HttpLoaderFactory
} from "water-utils";
import { HttpClientModule, HttpClient } from "@angular/common/http";
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
CenterModule,
NgZorroAntdModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
],
providers: [{ provide: NZ_I18N, useValue: zh_CN }],
entryComponents: [AppComponent]
})
export class AppModule {
//定义微服务
constructor(private injector: Injector) {
const strategyFactory = new ElementZoneStrategyFactory(
AppComponent,
this.injector
);
const customCosmos = createCustomElement(AppComponent, {
injector: this.injector,
strategyFactory
});
customElements.define("soa-demo", customCosmos);
}
ngDoBootstrap() {}
}
- ElementZoneStrategyFactory 工厂函数返回一个 Angular Component 和 Custom Elements 的桥梁策略类,创建和销毁组件引用,同时它还会在 input 改变时触发脏检查,示例:
...
const strategyFactory = new ElementZoneStrategyFactory(AppComponent, this.injector);
...
- createCustomElement 和 customElements.define 分别创建和定义一个自定义元素,其中 customElements.define 第一个参数为最终定义的自定义元素标签名称,示例:
- ts 代码
...
const customCosmos = createCustomElement(AppComponent, { injector: this.injector, strategyFactory });
customElements.define('soa-demo', customCosmos);
...
- 在根组件 app.component.ts 中定义微服务对外提供的接口,目前对外提供 5 个接口,2 个事件,如下:
接口说明
名称 | 说明 | 类型 | 默认值 |
---|---|---|---|
urlBase |
后台服务基础 url | string |
|
typeTheme |
主题切换方式(enum TYPETHEME { self, fork }; self:自切换,fork:跟随宿主应用切换) | string |
'self' |
theme |
主题配色(颜色值) | string |
@primary-color |
lang |
语言('zh', 'en') | string |
'zh' |
lessUrl |
调试 less | string |
|
onThemeChange |
主题改变时触发 | EventEmitter |
|
onLangChange |
语言改变时触发 | EventEmitter |
- html 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>soa-demo</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link
rel="stylesheet"
type="text/css"
href="https://jic.talkingdata.com/fa-static-resource/css/ng-cosmos-ui.min.css"
/>
</head>
<body>
<soa-demo></soa-demo>
</body>
</html>
扩展阅读:可重用网络组件
- 元素定义命名规范,标签以 soa-开头,后追加上该微服务英文名称,对应 js 文件以 soa.开头,命名同标签,示例:
//js命名
soa.soaname.js
//tag定义
<soa-soaname></soa-soaname>
- 微服务中不能使用路由,有需要用到路由的场景需要分拆服务
- 遵循angular 风格指南开发
- Tslint 语法规范
- SonarQube 规范
- 修改对应脚本和部署文件
- 修改 package.json 中"copy:bundle"项,示例:
"copy:bundle": "cpr dist/soa-elements/main.js deploy/soa/soa.soaname.js -o",
- 修改 deploy 目录 index.html 对应的 js 引用和 tag 调用,示例:
<html>
<head>
<meta charset="UTF-8" />
<base href="/" />
<title>soa demo for deploy</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
<link
rel="stylesheet"
type="text/css"
href="https://jic.talkingdata.com/fa-static-resource/css/ng-cosmos-ui.min.css"
/>
<!-- Gz share dep -->
<script src="https://jic.talkingdata.com/fa-static-resource/libs/soa.base.js"></script>
<!-- 这里修改对应js引用 -->
<!-- Custom Element For SOA -->
<script src="./soa/soa.demo.js"></script>
</head>
<body>
<!-- 这里修改对应tag调用 -->
<!-- Calling SOA -->
<soa-demo
urlBase="http://5990367be1e4470011c46fa8.mockapi.io"
typeTheme="self"
lessUrl="/assets/less/soa.demo.less"
></soa-demo>
<!-- Invoke -->
<script>
let soa = document.querySelector("soa-demo");
soa.lang = "en";
soa.theme = "blue";
soa.addEventListener("onThemeChange", e => {
console.log(`主题切换为:${e.detail}`);
});
soa.addEventListener("onLangChange", e => {
console.log(`语言切换为:${e.detail}`);
});
</script>
</body>
</html>
- 执行脚本
//部署微服务
$ npm run deploy
//更新微服务
$ npm run build
首先安装 water-utils(最新工程已经安装集成)
$ npm i water-utils
- 在根 app.module 中引入 water-utils 包,导入 TranslateModule, TranslateLoader, HttpLoaderFactory,同时导入依赖 HttpClientModule, HttpClient
...
import { TranslateModule, TranslateLoader, HttpLoaderFactory } from "water-utils";
import { HttpClientModule, HttpClient } from '@angular/common/http';
...
- 在@NgModule 装饰器中,声明模块
@NgModule({
imports: [
...
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
]
})
- 新建 app.translate.ts 文件,配置翻译,目前只配置中文和英文,统一根据微服务命名作为主 key(SOANAME),示例:
/**
* water-utils 多语言配置
* zh and en
* ot
*/
export const en = {
SOANAME: {
TITLE: "Welcome to microservices",
SELECT: "Change language",
THEME: "Change theme",
LAR: "large",
DEF: "default",
SML: "small"
}
};
export const zh = {
SOANAME: {
TITLE: "欢迎使用微服务",
SELECT: "选择语言",
THEME: "切换主题",
LAR: "大",
DEF: "中",
SML: "小"
}
};
- 在根组件 app.component.ts 中引入 TranslateService 和翻译配置文件
import { TranslateService } from "water-utils";
import { en, zh } from "./config/app.translate";
import { en_US, zh_CN, NzI18nService } from "ng-cosmos-ui";
- 在根组件中注入翻译服务,并初始化配置
constructor(public translate: TranslateService, private nzI18nService: NzI18nService ...) {
//初始化国际化配置
translate.setTranslation('zh', zh);
translate.setTranslation('en', en);
translate.addLangs(['zh', 'en']);
translate.setDefaultLang('zh');
}
- 调用翻译服务进行语言切换,示例:
this.translate.use(la);
this.nzI18nService.setLocale(la === "en" ? en_US : zh_CN);
1.在工程 src/assets/less 目录下新建 soa.name.less 主题配置文件,引入基础 less 配置文件,添加需要切换主题的样式,调用@primary-color 变量,示例:
@import url("https://jic.talkingdata.com/fa-static-resource/less/soa.base.less");
//自定义配置
.micro {
background:@primary-color
}
...
- 在根组件中引入 waterTheme 服务和环境变量
import WaterTheme from "water-utils";
import { environment } from "../environments/environment";
- 在根组件 ngOnInit 生命周期中初始化 less 配置文件,其中 lessUrl 会根据环境变量引入对应环境的 less 配置文件,示例:
...
lessUrl: string = environment.production ? "https://jic.talkingdata.com/fa-static-resource/less/soa.demo.less" : "/assets/less/soa.demo.less"
ngOnInit() {
WaterTheme.initLess(this.lessUrl);
}
...
- 调用 waterTheme 服务 changeTheme 方法切换主题配色
WaterTheme.changeTheme(color);
基于前端微服务架构的部署系统
基于 node + koa + mongodb ...
使用前端微服务部署系统上传、发布、引用微服务