组件化过程

工作情况

随着业务发展,主项目工程中集合了各种各样的第三方库或者自研的库。比如:阿里系、打点、蓝牙、视频、RN、国内版、海外版、白标版
通过git创建各类分支管理相关的需要,分支的主要情况有:

  • 公共分支common,用于处理国内与海外共同功能;
  • 国际化分支language,专门处理国际化文件、国际化切换,国际化字段编译校验;
  • 发版分支master
  • 线上分支release
  • 开发分支dev

仅仅是上面的情况,还能勉强整理处理,如果再加上...

  • 公共分支需区分本月上线与下月上线的common1、common2
  • 国际化分支需要裂变为国内国际化、海外国际化
  • 开发分支以功能为最小单元,演化出本月功能,下月分支。因此会出现一个人负责一个分支,到了另外一个月后,需要记得切换到新分支去工作
    最忙时,会在4、5个分支切来切去,经历过这种切来切切的场景,你会发现自己,再也记不住哪个功能具体在哪个分支上进行的开发了。每次开发新功能或者修复新问题,也要先问一圈,我在哪、我应该在哪?做...

准备之路

接收到老大需求,需要实现修改一个版本号就集成新功能到工程中。第一反应是需要建立公司自己的私有库,通过Pods管理不同的功能
需要怎么做呢?
以前做组件的过程都是一个组件一个仓库管理,这样做的优点:

  1. 完全独立,不担心产生耦合
  2. 使用方便,改为需要的版本后,直接pod install搞定
  3. 一般一个功能一个人开发就好,无过多的git提交冲突

缺点:

  1. 功能太过分散
  2. 如有code review功能,每次提交都要经过审核,效率降低
  3. 仓库过多,新人来,要运行主工程,需要给予他一群的仓库权限

开始之路

选择了创建两个仓库的模式进行组件开发,一个仓库管理所有的组件代码,一个管理所有的podspec。也不知道这个选择的路是对是错,后面的需求变动,也因为这个选择带来很多麻烦
需要使用的工具有

  1. Cocoapods依赖
  2. Gerrit代码审核
  3. Sourcetree处理git版本管理
  4. Xcode你懂得
  5. Shell

本地库怎么建,网上搜有一堆,或者看我的烂片,下面的脚本收好,不做pod lint检查的,修改里面两个地方后,就可以通过运行脚本的方式,快速提交到pod

#!/bin/bash
# 更新时间:2021-4-28
# 手动拷贝podspec到私有仓库更新
# 不通过lib lint检查
export LANG=en_US.UTF-8

tip="使用说明:直接git更新私有库推送spec,无lint验证操作,不符合正常流程规范,谨慎使用\n\
1.tag可先行推送,也可在此推送\n\
2.私有库路径有误时可手动设置localSpecGitDir\n\
3.最后spec确认推送前强行关闭或z取消,不会重置私有库修改,需手动删除\n\
4.最后spec确认不输入y会重置私有库修改,已推送tag需要手动处理"
echo -e "\033[34;1m$tip\033[0m"

spec_repo_name="看我,看我,改这里,自己的本地组件库名"

localSpecGitDir="看我,看我,改这里,索引仓库地址"

git reset --hard
echoError(){
    echo -e "\033[31;1m$1\033[0m"
}
echoNormal(){
    echo -e "\033[32;1m$1\033[0m"
}

spec_file=''
dir_file=$(dirname $0)
cd $dir_file
for file in `ls `
do
  if [[ $file =~ \.podspec$ ]];then
    spec_file=$file
    break
  fi
done

if [ "$spec_file" = "" ];then
    echoError "error:未找到spec文件"
    exit
fi
versionString=`grep -E 's.version.*=' $spec_file`
versionString=${versionString#*\'}
versionString=${versionString%*\'}

spec_filename=${spec_file%.*}

last_tag=$(git describe --tags `git rev-list --tags --max-count=1`)
if [ $? != 0 ]; then
     echoError "没有获取到tag"
fi
echoNormal "-------- 当前项目仓库最新 tag: ${last_tag} -----------------"
echoNormal "-------- 本地podspec tag: ${versionString} -----------------"
echoNormal "新tag:${versionString}(enter确认,手动输入其他终止)"
read newTag

if [ "" == "$newTag" ];then
    newTag=${versionString}
fi

if [ "$versionString" != "$newTag" ];then
    echoError "-----------------已手动终止-----------------"
    exit
fi

if [ "$last_tag" != "$newTag" ];then
    git tag ${newTag}
    git push origin HEAD:refs/tags/${newTag}
#    git push origin ${newTag}
    if [ $? != 0 ]; then
        echoError "-----------------推送tag失败,请检查网络环境-----------------"
        exit 1
    fi
fi

checkSpecGitDir(){
    if [ -d $spec_git_dir ];then
        echo
        else
        if [ "$1" = "" ]; then
        echoError "未找到spec仓库地址"
        exit 1
        else
        spec_git_dir=$1
        fi
    fi
}

#同级父目录下
spec_git_dir="$(dirname $(pwd))/${spec_repo_name}/"
#不存在可以手动设置
checkSpecGitDir ${localSpecGitDir}
#未找到再找找.cocoapods目录
checkSpecGitDir "${HOME}/.cocoapods/repos/${spec_repo_name}/"
#找不着
checkSpecGitDir ""

spec_content_dir=$spec_git_dir$spec_filename
target_dir=$spec_content_dir'/'$newTag
commitAction="Add"
if [ -d $spec_content_dir ];then
    commitAction="Update"
    else
    mkdir $spec_content_dir
fi
if [ -d $target_dir ];then
    rm -rf $target_dir
fi
mkdir $target_dir
target_file=$target_dir'/'$spec_file
cp $spec_file $target_file

resetSpec(){
    git reset --hard
    tag_dir="${spec_filename}/${newTag}/"
    if [ -d $tag_dir ];then
        rm -rf $tag_dir
    fi
}

cd $spec_git_dir
git pull origin

if [ $? != 0 ]; then
     echoError "-----------------pull spec 仓库失败,请检查网络环境-----------------"
     resetSpec
     exit 1
fi

message="[$commitAction] $spec_filename ($newTag)"
echoNormal "commit内容:$message"
echoNormal "----------------- 是否开始推送新的spec [输入'y'开始] -----------------------"
read answer
if [[ $answer != y ]]; then
    resetSpec
    exit 0
fi

git add -A
if [ $? != 0 ]; then
     echoError "-----------------spec git add失败-----------------"
     resetSpec
     exit 1
fi
git commit -m "$message"
git push origin
if [ $? != 0 ]; then
     echoError "-----------------push spec 仓库失败,请检查网络环境并重试-----------------"
     exit 1
else
     pod repo update ${spec_repo_name} --verbose
     if [ $? != 0 ]; then
          pod repo add ${spec_repo_name} ${localSpecGitDir}
          echoError "-----------------push spec 仓库失败,重试-----------------"
     exit 1
     fi
     echoNormal "-----------------push success-----------------"
fi


开发完毕

组件化完成后的结果如下,每一个目录是一个subspec,引入组件是,通过正常引入所有组件或者引入单个组件

pod 'IMILabKit'
//引入单个
pod 'IMILabKit/Log'
WeChat433dcd09cf407b1ce732a1f493fb15e6.png

需求变动

组件开发到中后期时,说需要对外提供,因此就面临不能使用源码作为组件的问题。查找cocoapods二进制方案,大概有3类

  • cocoapods-package命令打包生成二进制
  • cocoapods-binary配置生成二进制
  • 使用cocoapods管理framework
  • ENV条件编译生成不同的包

其实cocoapods执行完毕后,在pod目录下有一个framework产生,没有去尝试这个framework是否能直接用于作为二进制方案(子组件化,这种机制不适合我们的场景,因此没有去做尝试)

  • 转换为二进制最大的困难
    共用同一套代码,cocoapods子组件形式在使用时其实还是在同一个module中,子组件变成一个个独立的framework就将现有现象变成在不同的module中,要解决一个个的兼容问题,模块引入在两种不同方式是不一样的,因为这点,需要处理比较多的细节
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容