一、实现跨Git项目复用组的探测之旅

2020-09-20 loading

近期在 Angular 项目开发过程中,有个需求,同样的界面需要在两个不同的项目用到(用户端、管理端)。于是,大家决定增加一个 Git 仓库,用于放置多项目复用的组件!

背景:由于该项目有很多权限限制,发布 npm 包需要走很多流程,所以,下面的方法尝试中,会使用优先不发包的方式!

# 一、使用 subtree

思路:

  • 新建一个子项目https://github.com/Heyff12/reuseSon.git,该项目是一个完整的可以启动、编译的 angular 项目,方便引用并测试公用组件
  • 在 src 目录之外,新建 reuse/src 目录,在该目录下,编写公用组件代码
  • 第三方需要使用该公用组件的库,只需要拉取 reuse/src 目录即可

以下操作是在第三方库执行的操作

# 1、 拉取子项目代码

git subtree add --prefix=reuse https://github.com/Heyff12/reuseSon.git master --squash

# 2、修改后提交代码到子项目

需要先把当前修改提交到本项目(第三方项目),再执行下面的 subtree 推送

git subtree push --prefix=reuse https://github.com/Heyff12/reuseSon.git master

这个提交会更新 subtree 的库的代码; subtree 库需要 pull 获取最新改动

# 3、 拉取子项目最新代码

git subtree pull --prefix=reuse https://github.com/Heyff12/reuseSon.git master --squash

# 4、弊端

  • 在 angular 项目中,组件需要 在 module 注册。 拉取过来的公用组件的 module 需要受到在第三方项目的 app.module.ts 中引入
  • 需要增加配置编译

文件 tsconfig.app.json

"include": [
    "reuse/src/app/components/**/*.ts",
  ],
  "exclude": [
    "reuse/src/app/components/**/*.spec.ts"
  ]

# 二、发布 npm 包

思路:

  • 基于第一种方式,subtree 的操作有些繁琐,故尝试发包的方式

# 1、 在子项目发包

  • npm init
  • 新建 .npmignore 忽略文件
  • npm login
  • npm publish

备注: 包的名字以@开头时,比如 @hey_ff/testbutton,发布时,需要增加属性才能发包成功

npm publish --access public

# 2、在第三方项目安装插件

npm install @hey_ff/testbutton

# 3、使用方式

  • 引入

文件 app.module.ts

import {TheButtonComponent} from '@hey_ff/testbutton/the-button/the-button.component'

@NgModule({
  declarations: [
    AppComponent,TheButtonComponent
  ],
  • 发包的代码,即reuse/src 目录,是原生的未经编译的 angular 代码,所以需要在第三方项目进行编译配置

文件 tsconfig.app.json

"include": [
    "node_modules/@hey_ff/testbutton/the-button/**/*.ts",
  ],
  "exclude": [
    "node_modules/@hey_ff/testbutton/the-button/**/*.spec.ts",
  ]

# 4、总结

跟第一种方式比起来:

  • 只是把获取公用组件库代码的方式从 subtree 换成了 npm install,整体并没有简化实际使用中的繁琐配置
  • 并且不能像第一种方式一样,可以更改子项目代码

# 三、子项目不发包,通过拉取公用组件代码,配置绝对路径到 package.json 实现引用

在前两种方式对比下,发布包也依然没有让使用变得更简洁,所以继续尝试不发包的方式。

# 1、将子项目的代码拉取到第三方项目,也可以使用第一种里面的 subtree 路径

# 2、修改第三方项目的 package.json,给公用组件的路径指定引入名称

"btn": "file:./reuse/src/app/components",

# 3、在 app.module.ts 引入


import {TheButtonComponent} from 'btn'

@NgModule({
  declarations: [
    AppComponent,TheButtonComponent
  ],

# 4、在 tsconfig.app.json 种加入编译

"include": [
    "reuse/src/app/components/**/*.ts",
  ],
  "exclude": [
    "reuse/src/app/components/**/*.spec.ts"
  ]

# 5、总结

  • 在目前的 3 种方法中,我们的子项目是一个完全可以自运行的项目。
  • 在第三方项目中,引用的只是子项目中的部分组件原代码(因此在使用时,需要编译)
  • 通过 subtree 的方式,可以在第三方项目,同步对子项目进行开发调试

# 四、子项目不发包,通过配置代码 Url 到 package.json 实现引用

上述方式,既然通过配置 package.json 实现,那依据 package.json 的功能,还可以不用拉取公用组件的代码实现!

https://github.com/Heyff12/reuseBtn 这个库,只有公用组件的代码

# 1、修改第三方项目的 package.json

"btnUrl": "https://github.com/Heyff12/reuseBtn",

# 2、在 app.module.ts 引入

import {TheButtonComponent} from 'btnUrl'

@NgModule({
  declarations: [
    AppComponent,TheButtonComponent
  ],

# 3、在 tsconfig.app.json 种加入编译

"include": [
    "node_modules/btnUrl/**/*.ts",
  ],
  "exclude": [
    "node_modules/btnUrl/**/*.spec.ts",
  ]

# 4、总结

基于目前的 4 种方式,只是优化了引入公用组件库的方式,实际使用依然繁琐,就当做是对于 package.json 的引用探索好了~

使用的繁琐,归根结底,就是由于引入的公用组件代码没有经过编译!!!

通过再次查看 angular 文档,下面着重进行制定代码的编译实现!

# 五、子项目发布编译后的 angular 组件包

# 1、在子项目构建 library 配置,可以 build、发布编译打包后的组件包

1.创建工作区

ng new xxxx --create-application=false

xxxx 为项目名

2.进入项目新建文件夹

cd xxxx

ng g library my-lib --prefix=ml

3.编译 ng build my-lib --prod

4.编译后会生成 dist 文件,进入 dist 文件 cd dist cd my-lib

5.打包

npm pack

6.发布 npm publish --access public

# 2、在第三方项目安装包,可以直接使用

import { MyLibModule } from '@hey_ff/my-lib';

@NgModule({
  declarations: [AppComponent, TheButtonComponent],
  imports: [BrowserModule, AppRoutingModule, MyLibModule],

# 3、如果不方便发布到 npm

1、在公用组件项目,把第一步的 打包好的文件 dist/my-lib push 到指定分支

git subtree push --prefix dist/my-lib origin reuse

2、在第三方项目 通过 指定分支路径 安装上面的打包好的文件

"reuse": "git@github.com:Heyff12/angularPackage.git#reuse",

3、 在第三方项目,正常使用

import { MyLibModule } from 'reuse';

@NgModule({
  declarations: [AppComponent, TheButtonComponent],
  imports: [BrowserModule, AppRoutingModule, MyLibModule],

# 4、总结

  • 这种方式构建的子项目,是一个完整的可运行的项目,可以调试公用组件库 projects/my-lib
  • 在第三方项目,应用的是 打包编译好的 my-lib 的代码,不含其它冗余代码;不需要编译

# 六、不发 npm 包的最佳方案

  • 第五种方式的,第 3 步

# 七、反思

上述实现过程,看完后感觉很扭曲。

  • 为啥不发 npm 包?—— 特定项目,导致发包申请流程复杂,于是大家想走不麻烦更多无关人员的途径 😢
  • 为啥在 package.json 浪费了时间?——误入歧途,陷入了对 package.json 的探索 😿
  • 为啥不直接编译?—— 源自一个美好的不太成熟的想法,所有使用公用组件库的项目,都可以自行更改公用组件库的代码

# 八、总结

  • 既然要开发公用组件,就保持公用组件开发的统一性,只在公用组件仓库进行代码开发和调试,其他库只负责使用
  • 在公用组件仓库,配置可以对公用组件进行调试的设置
  • 对于公用组件代码,一定进行编译打包,保障使用的简洁
  • 在公用组件库,编译时,只编译公用组件的代码
  • 虽然该文章以 angular 为例,也希望大家在其他语言开发遇到类似场景时,少走弯路!

# 九、相关库