前言
最近团队在推行微前端这件事情,经过前期的探索,逐渐拟出了一个草案,并且现在按照草案一个个开始去实现,这次文章涉及到的是微前端如何去实现共享,主要讲其中一种实现方式git submodule
共享方式
1: npm:
- 由于我们的代码是需要保密的,所以只能搭建内部类似npm的包管理工具,但是可能需要其他人帮忙,走流程很浪费时间
- 做成npm插件的话 需要写出合理的webpack配置,我们的共享文件有函数,组件,样式复杂度上升
2:CDN
同上
3:git submodule
经过我们的探究,git submodule就可以做这样的事情,并且在微前端实现里面正好有这个解决方案,而且网上也已经有团队使用他,并且他不需要任何额外的人和资源去实现,仅仅前端就能完成,就是需要一点学习成本,下面就来讲一下具体的使用流程
什么是git submoudle
借用网上的一段话,大致的描述如下
有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。
Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。
使用流程
知道了git submodule是什么我们现在来着重说一下使用流程
场景1
需要新建一个父项目,并且包含子项目
首先我在gitlab上面创建了一个share子项目,当作我们的共享项目(子模块)
然后我们在gitlab上再新建一个父项目microFront3如下
父项目有了,子项目也有了,现在做的事情就是在父项目放一个文件,然后引入子项目
- 父项目文件
- 此时如何引用项目了? 使用如下命令
git submodule add https://xxxxxxx.git shares-folder
其中shares-folder是文件夹名可以自己指定,执行了这个命令之后我们看看效果
我们发现此时文件夹名并不是想要的shares-folder,而是share这是为什么了,是因为我们手误执行命令的时候少写了文件名
所以现在子项目不是我们想要的,我们需要删除重新创建一个,但是子项目的删除没有那么简单,下面就来操作下网上经常说的那些删除子项目步骤,但是很多文章没有实际的操作不好理解,现在就来试一下
-
第一步直接右键删除这两个文件(share,.gitmodules)
虽然文件消失了,但是当我们再次执行添加命令时,会报如下错误
可能不详细,我们在看看git status的结果
我们会发现share和.gitmodules确实被修改删除掉了,但是他们也存在于暂存区,这也是为什么他难删除的原因,你执行了git submodule add xx的操作后其实已经帮你放到暂存区了,那该怎么做了,先把暂存区的删掉
git rm --cache .gitmodule
git rm --cache share
执行完之后看看效果
好了达到预期的效果了,我们在来执行添加命令
这次成功了但是有一个小问题,问题是什么了?这次之所以成功是因为之前的文件夹名称是share,现在是shares-folder,如果两次的文件名字是一样的还是有问题,再来测试下,同样的步骤删除掉shares-folder,在执行添加操作如下
我们发现没有成功,说的是我们本地已经有一个shares-folder,如果想要成功拉取,需要换一个名字,这就是为什么刚刚第一次操作可以成功,因为share和shares-folder名字不一样,但是这次失败,那怎么解决了,网上有第二个命令
rm -rf .git/modules/shares-folder
执行此删除命令后再次执行添加子项目命令,查看结果
我们发现这次成功了
- 总结
删除子模块的操作时
1:右键删除文件夹,或者命令删除
2:git rm --cache .gitmodules, git rm --cache 文件夹名称
3:rm -rf .git/modules/文件夹名称
PS:1,2两步可以用git rm share和git rm .gitmodules代替,不用--cache表示工作区也一起删除
好了,子项目已经有了,父项目也已经有了一个README.md。我们现在直接上传,对着gitlab仓库的提示执行命令就行,结果如下
场景2
需要克隆已经有子项目的仓库
刚刚我们已经创建了microFront3,符合我们这个场景,现在我们就拿这个项目来做一个例子。
在本地创建一个microFront3-copy文件夹,直接克隆效果如下
我们发现文件夹确实是有的但是里面没有内容,所以我们还需要其他命令来达到效果
cd shares-folder
git submodule init
git submodule update
执行以上命令就可以看到内容了,效果如下
如果觉得这样麻烦的话,在克隆时候也是可以一步到位,只是命令需要改一下,大家自行尝试下
git clone --recursive https://xxxxx.git
--recursive 表示会递归克隆,检测到父项目里面有子项目会自动克隆下去
场景3
需要修改子项目 并且让其他父项目中的子项目更新
现在来说一下如何更改子项目,以及如何更新其他父项目中的子项目,我的gitlab之前已经创建了microFront2,就用microFront2和microFront3来做例子
我在microFront2中的shares-folder加一个test.txt文件,然后执行git status结果如下
说明
- 子项目的改变需要在子项目内部提交,执行git add git commit 等操作
- 子项目提交完了之后,在cd .. 来到父项目,查看git status会发现,虽然子模块已经提交了,但还是有shares-folder的改动记录,这个是正常的
-
在父目录提交之后我们发现一个问题
这里面有一个hash值,这个hash值就是子目录里面最新的一次提交对应的hash值
-
递归克隆就是根据这个hash值来获取子项目
克隆下来发现子项目是79e9fd对应的代码,此时还可以看到子项目在一个游离的分支上(79e9fd),注意游离的分支是提交不了的,查看记录这个hash值其实就是master分支最新一次提交,所以直接切换到master分支就行,这句话如果不理解可以自己手动尝试下,可能会好理解一点
- 子项目改变提交了子项目之后,一定要把父项目也一起提交了
更新其他父项目中的子项目
上面子项目已经更新了一部分代码了,但是其他父项目中的子项目还是旧代码(因为没有更新),那如何更新了?现在microFront3中的子项目是旧代码,我们更新他可以有两种方法
方法1
git submodule update --remote
这行命令就可以把远程的子项目更新到本地
注意执行这行命令的时候不要进去子项目,就在父项目里面执行,然后执行git status
还是有修改了,为什么了?刚刚的命令是本地的子项目更新了,如果你不把本地这个最新的hash值提交到gitlab上去,下次克隆根据hash去找子项目的时候还是旧的代码
方法2
cd shares-folder
git pull
注意这个是需要在子项目中操作的,子项目提交完了,直接cd .. 提交父项目
场景4
切换分支情况
切换分支的疑惑
- 父项目里面的出现了一个新分支,子项目也会有这个新分支么
- 子项目如何做到分支更新,之前更新的一直都是master分支
创建分支
我们这次用microFront2,microFront3项目做例子,microFront3新建了一个分支如下,查看share仓库
父项目增加了一个test分支,但是子项目没有这个分支
此时说明了一点就是,父项目和子项目是单独开来的
子项目创建分支,并更新
我们先给子项目也创建一个分支test,在microFron2子项目中拉取test并且增加新纪录,依次提交。在microFront3执行更新操作,虽然此时是在microFront3子项目中的test上,但是一旦直接更新命令,就会自动跳到master分支的最新一次提交如下
由此可见这些更新命令只会更新master,所以网上建议公共的子项目就维护一个master分支,这样就少了很多事情。
那如果非要更新test分支怎么做了,这个时候需要改一下配置如下
git config -f .gitmodules submodule.shares-folder.branch test
shares-folder是文件名,test是分支名,执行完成之后看一下.gitmodules的配置如下
多了一个branch = test的信息,如果执行上面的配置命令没有生效,可以自己手动添加,然后再执行
git submodule update --remote 效果如下
这就达到了我们预期的效果,最后还是不要忘了把主目录也提交上去
总结
以上是我想到的使用git submodule的场景,因为我们项目只需要一个子项目,所以没有涉及到多个子项目的情况,但是感觉操作都是一样的,就是繁琐一点,如果有写的不对的欢迎指出来