E.F.S.F. E.F.S.F.

销声匿迹 沉默是金

目录
Angular6
/        

Angular6

入门

官方文档

高阶

修仙之路

构建第三方包

angular-cli 的 ng g lib 不太好用,所以还是用 ng-packgr

建立父项目

ng new project --style less --prefix pre

调整项目结构

cd project
# 建立第三方包文件夹
mkdir -p projects/mylib
# 在父项目中生成模块
ng g module mylib
# 将mylib.module.ts移动到 project/mylib下
mv mylib.module.ts ./projects/mylib
# 在project/mylib下生成component/service
# 注意,component要export出来
cd project/mylib
ng g c mycomponent
ng g s myservice
# 至此基本项目结构完成

模块依赖

当你编写第三方依赖包的时候,你的 service/component 或许需要一些数据来驱动,往往这些数据/对象是使用者提供的

# 建立model文件夹
mkdir -p project/mylib/model

新建一个类

export class AuthConfigModel {

  // cas登录地址
  private _casurl: string;
  // springboot网关地址
  private _zuulurl: string;

  constructor(cas?, zuul?) {
    this._casurl = cas;
    this._zuulurl = zuul;
  }


  get casurl(): string {
    return this._casurl;
  }

  set casurl(value: string) {
    this._casurl = value;
  }

  get zuulurl(): string {
    return this._zuulurl;
  }

  set zuulurl(value: string) {
    this._zuulurl = value;
  }
}

建立好 model 后要记得要建立导出 ts,这里我们在 model 文件夹下建立 index.ts

// 导出本文件夹下的model
export * from './auth.config.model';

现在基本的数据格式建立好的,如何让使用者在外部注入对象?在 mylib.module 中编写

// 注意 Module名称换为MylibModule
@NgModule({})
export class AuthModule {
  // 外部调用 AuthModule.forRoot(new AuthConfigModel('',''))
  // 这样值就注入进来了
  public static forRoot(config): ModuleWithProviders {
    return {
      ngModule: AuthModule,
      providers: [
        // 本模块调取值时key = authconfig
        // useValue:不要忘记加范型
        {provide: 'authConfig', useValue: <AuthConfigModel>config}
      ]
    };
  }
}

外部调用 demo,在 AppModule 中

const authConfigModel = new AuthConfigModel(
  "http://xxx",
  "http://www.baidu2.com"
);

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpClientModule,
    NgZorroAntdModule,
    // 这里是调用的方式
    AuthModule.forRoot(authConfigModel)
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: CookieInterceptor, multi: true },
    { provide: NZ_I18N, useValue: zh_CN },
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

外部调用完成,现在要使用注入的值,在mylibservice 中

export class AuthService {
  constructor(
    // 通过inject(key)注入
    @Inject("authConfig") private config: AuthConfigModel,
    private http: HttpClient
  ) {
    this.load();
  }

  load() {
    console.log(this.config);
  }
}

当然 service 也要导出

ng-packagr

# 安装依赖
npm install --save-dev ng-packagr tsickle

在 project/mylib 下生成 package.json

npm init

在 project/mylib 下建立 public_api.ts 放出供别人使用的 ts

touch public_api.ts

这里我将 model interceptor service 拆分开,每个文件夹下都有 index.ts 负责导出自己文件夹下的 ts,所以我只需要将各个文件夹下的 index.ts 导出就可以

export * from './auth.module';
export * from './interceptors/index';
export * from './services/index';
export * from './models/index';

修改 package.json,使用时删除注释

{
  // 包名称
  "name": "@ferried/mylib",
  // 包版本
  "version": "0.0.0-alpha",
  // 包描述
  "description": "",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  // 作者
  "author": "ferried<harlancui@outlook.com>",
  "peerDependencies": {
    "@angular/core": ">=6.0.0",
    "@angular/common": ">=6.0.0"
  },
  // ng-packagr依赖
  "ngPackage": {
    // 通过schma.json打包
    "$schema": "../node_modules/ng-packagr/ng-package.schema.json",
    "lib": {
      // 模块
      "flatModuleFile": "mylib",
      // 导出文件入口
      "entryFile": "public_api.ts"
    },
    // 打包后dist出口
    "dest": "../../dist/@ferried/mylib"
  }
}

在根 package.json 配置打包命令

"scripts": {
    "build:mylib": "ng-packagr -p projects/mylib",
  },

注意,以上我是通过粘贴已经写好的代码写出的,具体的 auth 要切换成你们的 mylib,比如 AuthModule-> MylibModule,export ... form auth -> export ... form mylib

执行打包

yarn build:auth

会在 outfile 中打包完毕

# 打开打包后的文件夹
cd outfile
# 登录
npm login
# 发布
npm publish

validate-commit

多人项目不好管理代码提交描述格式各样,所以我们要引入 validate-commit 来规范化代码提交

安装

# 安装commit msg 验证包
npm install --save-dev validate-commit-msg

现在我们拥有了验证包,但是还需要另外一个包去触发它,也就是钩子

# 安装hook包
npm install --save-dev husky

配置

在根项目 package.json 中配置

  "husky": {
    "hooks": {
      "commit-msg": "validate-commit-msg"
    }

测试

git commit -m "foo: this will fail"

# 提示错误
husky > commit-msg (node v9.11.0)
⧗   input:
foo: this will fail

✖   type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum]
✖   found 1 problems, 0 warnings
husky > commit-msg hook failed (add --no-verify to bypass)

代码提交格式

<type>[optional scope]: <description>

[optional body]

[optional footer]

解释

type 用于表示此次改动的类型,目前常用的主要有以下几种:
feat 新功能(feature)表示在代码库中新增了一个功能(这和语义化版本中的 MINOR 相对应)
fix 表示在代码库中修复了一个 bug(这和语义化版本中的 PATCH 相对应)
docs 文档(documentation)
style (格式化, 缺失分号等; 不包括生产代码变动)
refactor (重构代码)
perf (性能优化)
test (添加缺失的测试, 重构测试, 不包括生产代码变动)
chore (更新grunt任务等; 不包括生产代码变动)
scope:一个可选的修改范围,用于标识此次提交主要涉及到代码中哪个模块。
description:简明扼要描述本次提交的内容,首字母无需大写,结尾不需要使用 .。
optional body:详细描述本次提交,比如此次变更的动机,如需换行,则使用 |。
optional footer:描述与之关联的 issue 或 break change。

正确提交 demo

git commit -m "feat(mylib): add something in it"

changelog

当我们每次提交的都很规范的时候,就可以利用 commit 来生成版本变化文件

安装依赖

npm install --save-dev conventional-changelog-cli

配置

在根 package.json 中写入

"scripts": {
    "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s --pkg package.json",
  },

运行

yarn changlog

生成的文件

# 0.0.0-alpha (2018-11-18)
### Bug Fixes
* **angular-yuznai:** storybook初始化方式由getStoryBook切换为官方推荐方式sb.init ([1f0d38e](xxx/1f0d38e))
* **auth:** 增加authConfigModel注释并测试compodc ([4e024a8](xxx/4e024a8))
* **auth,uis:** 修复uis模块打包目录问题,修复auth注释问题,发布auth,uis-0.0.0-a版本 ([6563854](xxx/6563854))
* **auth,uis,angular-yunzai:** fix package floads ([fcd5f32](xxx/fcd5f32))

### Features

* **angualr-yunzai:** 增加Compodoc文档插件,StoryBook组件演示插件,命令在package.json中 ([f746dc4](xxx/f746dc4))
* **angular-yuznai:** add changelog ([f63fe58](xxx/f63fe58))
* **auth:** 添加cookie跨域拦截器,添加auth2token拦截器(未实现),添加token对应service和model.config ([9fed596](xxx/9fed596))

compodoc

我们拥有了一个比较健全的产品,但是还缺乏 API 列表这样的文档,通过 compodoc 来实现

安装

npm install --save-dev @compodoc

配置

 "scripts": {
    "compodoc": "compodoc -r 5555 -p tsconfig.json -s",
  },

运行

yarn compodoc

storybook

我们写第三方库的时候一定会有将 demo 展示出来的需求,这就用到了 storybook

安装

# 安装cli
npm install --save-dev @storybook/cli
# 初始化
# sb = storybook
sb init

在你的项目中会生成.storybook 文件夹,那里是存放的是配置,
在 src/app/stories 中会生成 index.stories.ts

配置

"script":{
  "storybook": "start-storybook -p 6006",
},

运行

yarn storybook

新增用例

import { storiesOf, moduleMetadata } from "@storybook/angular";
import { withNotes } from "@storybook/addon-notes";
import { action } from "@storybook/addon-actions";
import { linkTo } from "@storybook/addon-links";

import { Welcome, Button } from "@storybook/angular/demo";
import { CommonModule } from "@angular/common";
import { HttpClientModule } from "@angular/common/http";
import { AppComponent } from "../app/app.component";
import { AuthConfigModel, AuthModule } from "@ferried/auth";

storiesOf("My Panel", module)
  .addDecorator(
    // 模块依赖
    moduleMetadata({
      imports: [
        CommonModule,
        HttpClientModule,
        AuthModule.forRoot(new AuthConfigModel("asdf", "qwer"))
      ],
      schemas: [],
      declarations: [AppComponent],
      providers: []
    })
  )
  .add("default", () => ({
    component:AppComponent
  }));

发布版本

配合以下步骤标准工作流

新功能/新bug
拉最新master分支
从master检出一个分支(只做一件事儿)
提交分支(注意commit格式)
合并分支
提交master

发布版本

配置命令
{
  "script":{
    "version": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0 && git add CHANGELOG.md"
  }
}

最后

yarn version
输入版本号
git 打 tag
推送master

本地测试

yarn build完成你的第三方包后
# 直接用yarn安装本地dist里打包好的
yarn add ../../dist/project
# 最后你的package.json中会加入第三方包
# 注入模块本地运行测试

结束

我会创建 lssues,如果文档哪步出错可以下方提出,我会解决并更新文档内容,右上方援助难民二维码


标题:Angular6
作者:devcui
地址:https://blog.eiyouhe.com/articles/2019/08/19/1566176660956.html