微前端实现共享方式之-- git submodule 使用说明

3,816 阅读9分钟

前言

最近团队在推行微前端这件事情,经过前期的探索,逐渐拟出了一个草案,并且现在按照草案一个个开始去实现,这次文章涉及到的是微前端如何去实现共享,主要讲其中一种实现方式git submodule

共享方式

  • npm

    • 由于我们的代码是需要保密的,所以只能搭建内部类似npm的包管理工具,但是可能需要其他人帮忙,走流程很浪费时间
    • 做成npm插件的话 需要写出合理的webpack配置,我们的共享文件有函数,组件,样式复杂度上升
  • CDN

    同上

  • git submodule

    经过我们的探究,git submodule就可以做这样的事情,在微前端实现里面正好有这个解决方案,而且网上也已经有团队使用他,并且他不需要任何额外的人和资源去实现,仅仅前端就能完成,就是需要一点学习成本,下面就来讲一下具体的使用流程

什么是git submoudle

借用网上的一段话,大致的描述如下

有种情况我们经常会遇到:某个工作中的项目需要包含并使用另一个项目。 也许是第三方库,或者你独立开发的,用于多个父项目的库。 现在问题来了:你想要把它们当做两个独立的项目,同时又想在一个项目中使用另一个。 Git 通过子模块来解决这个问题。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录。 它能让你将另一个仓库克隆到自己的项目中,同时还保持提交的独立。

使用流程

git submodule我们已经了解了,现在来着重说一下它的使用流程

场景1

需要新建一个父项目,并且包含子项目

首先我在gitlab上面创建了一个share子项目,当作我们的共享项目(子模块) image.png 然后我们在gitlab上再新建一个父项目microFront3如下 image.png

父项目有了,子项目也有了,现在做的事情就是在父项目放一个文件,然后引入子项目

  • 父项目文件

image.png

  • 此时如何引用子项目了? 使用如下命令

git submodule add xxxxxxx.git shares-folder

其中shares-folder是文件夹名可以自己指定,执行了这个命令之后我们看看效果

image.png

我们发现此时文件夹名并不是想要的shares-folder,而是share这是为什么了,是因为我们手误执行命令的时候少写了文件名

image.png

所以现在子项目不是我们想要的,我们需要删除重新创建一个,但是子项目的删除没有那么简单,下面就来操作下网上经常说的那些删除子项目步骤,但是很多文章没有实际的操作不好理解,现在就来试一下

  • 第一步直接右键删除这两个文件(share,.gitmodules)

虽然文件消失了,但是当我们再次执行添加命令时,会报如下错误

image.png

可能不详细,我们在看看git status的结果

image.png

我们会发现share和.gitmodules确实被修改删除掉了,但是他们也存在于暂存区,这也是为什么他难删除的原因,你执行了git submodule add xx的操作后其实已经帮你放到暂存区了,那该怎么做了,先把暂存区的删掉

git rm --cache .gitmodule git rm --cache share

执行完之后看看效果

image.png

好了达到预期的效果了,我们在来执行添加命令

image.png

这次成功了但是有一个小问题,问题是什么了?这次之所以成功是因为之前的文件夹名称是share,现在是shares-folder,如果两次的文件名字是一样的还是有问题,再来测试下,同样的步骤删除掉shares-folder,在执行添加操作如下

image.png

我们发现没有成功,说的是我们本地已经有一个shares-folder,如果想要成功拉取,需要换一个名字,这就是为什么刚刚第一次操作可以成功,因为share和shares-folder名字不一样,但是这次失败,那怎么解决了,网上有第二个命令

rm -rf .git/modules/shares-folder

执行此删除命令后再次执行添加子项目命令,查看结果

image.png 我们发现这次成功了

  • 总结

删除子模块的操作时

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仓库的提示执行命令就行,结果如下 image.png

场景2

需要克隆已经有子项目的仓库

刚刚我们已经创建了microFront3,符合我们这个场景,现在我们就拿这个项目来做一个例子。 在本地创建一个microFront3-copy文件夹,直接克隆效果如下

image.png

我们发现文件夹确实是有的但是里面没有内容,所以我们还需要其他命令来达到效果

cd shares-folder git submodule init git submodule update

执行以上命令就可以看到内容了,效果如下

image.png 如果觉得这样麻烦的话,在克隆时候也是可以一步到位,只是命令需要改一下,大家自行尝试下

git clone --recursive xxxxx.git

--recursive 表示会递归克隆,检测到父项目里面有子项目会自动克隆下去

场景3

需要修改子项目 并且让其他父项目中的子项目更新

现在来说一下如何更改子项目,以及如何更新其他父项目中的子项目,我的gitlab之前已经创建了microFront2,就用microFront2和microFront3来做例子 我在microFront2中的shares-folder加一个test.txt文件,然后执行git status结果如下 image.png

说明

  • 子项目的改变需要在子项目内部提交,执行git add git commit 等操作

  • 子项目提交完了之后,cd .. 到父项目,查看git status会发现,虽然子模块已经提交了,但还是有shares-folder的改动记录,这个是正常的

  • 在父目录提交之后我们发现一个问题

image.png

这里面有一个hash值,这个hash值就是子目录里面最新的一次提交对应的hash值

  • 递归克隆就是根据这个hash值来获取子项目

image.png

克隆下来发现子项目是79e9fd对应的代码,此时还可以看到子项目在一个游离的分支上(79e9fd),注意游离的分支是提交不了的,查看记录这个hash值其实就是master分支最新一次提交,所以直接切换到master分支就行,这句话如果不理解可以自己手动尝试下,可能会好理解一点

  • 子项目改变提交了子项目之后,一定要把父项目也一起提交了

更新其他父项目中的子项目

上面子项目已经更新了一部分代码了,但是其他父项目中的子项目还是旧代码(因为没有更新),那如何更新了?现在microFront3中的子项目是旧代码,我们更新他可以有两种方法

方法1

git submodule update --remote

这行命令就可以把远程的子项目更新到本地

image.png

注意执行这行命令的时候不要进去子项目,就在父项目里面执行,然后执行git status

image.png

还是有修改了,为什么了?刚刚的命令是本地的子项目更新了,如果你不把本地这个最新的hash值提交到gitlab上去,下次克隆根据hash去找子项目的时候还是旧的代码

方法2

cd shares-folder git pull

注意这个是需要在子项目中操作的,子项目提交完了,直接cd .. 提交父项目

场景4

切换分支情况

切换分支的疑惑

  • 父项目里面的出现了一个新分支,子项目也会有这个新分支么
  • 子项目如何做到分支更新,之前更新的一直都是master分支

创建分支

我们这次用microFront2,microFront3项目做例子,microFront3新建了一个分支如下,查看share仓库

image.png

父项目增加了一个test分支,但是子项目没有这个分支

image.png

此时说明了一点就是,父项目和子项目是单独开来的

子项目创建分支,并更新

我们先给子项目也创建一个分支test,在microFron2子项目中拉取test并且增加新纪录,依次提交。在microFront3执行更新操作,虽然此时是在microFront3子项目中的test上,但是一旦直接更新命令,就会自动跳到master分支的最新一次提交如下

image.png

image.png

由此可见这些更新命令只会更新master,所以网上建议公共的子项目就维护一个master分支,这样就少了很多事情。 那如果非要更新test分支怎么做了,这个时候需要改一下配置如下

git config -f .gitmodules submodule.shares-folder.branch test

shares-folder是文件名,test是分支名,执行完成之后看一下.gitmodules的配置如下

image.png

多了一个branch = test的信息,如果执行上面的配置命令没有生效,可以自己手动添加,然后再执行 git submodule update --remote 效果如下 image.png

这就达到了我们预期的效果,test分支上的代码被更新了,最后还是不要忘了把主目录也提交上去

总结

以上是我想到的使用git submodule的场景,因为我们项目只需要一个子项目,所以没有涉及到多个子项目的情况,但是感觉操作都是一样的,就是繁琐一点,如果有写的不对的欢迎指出来