Cocopods 本身是一个优秀的 iOS 开发的包管理工具,涵盖了 7k+ 的开源组件,包管理库是托管在 Github。
由于众所周知的原因它的速度日渐缓慢,有时会频繁报如下错误:

1
2
3
4
$ pod install
Cloning into '/path/to/ios/project/Pods/xxx'
error: RPC failed; result=52, HTTP code = 0
fatal: The remote end hung up unexpectedly

本文主要为解决该问题而诞生的,以下的加速方案不局限于目前已流传的优化方案,而是在此基础上彻底的加速!

  • 使用淘宝 Ruby Gems 源(Cocoapods 使用 ruby 开发)

  • pod install 时不设置包的更新:参考文章

  • 使用国内 git 服务器镜像 Cocoapods Spec: 参考文章

如果你对 Cocoapods 有更深层次的理解,请参见:objc.io: Cocoapods under the hood 中文版本

今天早晨看到微博众多 iOS 开发者赞同转发《CocoaPods最佳实践探讨》一文,
针对 Pods 建议纳入版本控制也是无奈之举。之前公司项目中也是这样施行很长一段时间,不排除更新可能会造成很多无用信息”刷屏”,偶尔还会因为版本冲突造成一些混乱状况需要处理。个人还是更倾向于精简原则,遵循官方的建议。

大家都是技术人员,其实这些小问题难道因为 github 倒下就没有解决方案了吗?!看我如何撕破这层纸老虎:

技术概述

  • Cocopods v0.34.0+

  • gitlab: 自建私有 git 服务器

  • gitlab-mirrors: 专用于 github 镜像至 gitlab 并保持定期更新

  • rake: ruby 的代码构建工具(不懂 ruby 的可以把它理解为命令聚合工具)

技术剖析

Cocoapods 自身支持私有仓库
恰好的是就在前不久发布的 0.34.0 版本支持 Podfile
添加多个的包源仓库,举个例子:

1
2
3
4
pod 'AFNetworking'
pod 'Mantle'

这个特性其实是为了扩充官方 Spec 的同时可以更好的让开发者管理私有的公共组件,那我同样是从这里下手:

前提是自己以及搭建好 gitlab 服务器:官方教程 (Ubuntu) | 本人教程 (CentOS)

自力更生

首先我们需要创建一个自己的 Spec 仓库,目录结构如下:

1
2
3
4
5
6
.
├── CocoaPods-version.yml
├── Specs/
├── README.md
├── Rakefile
└── Gemfile

配置不做详细描述,这里比官方多了两个文件 Rakefile 和 Gemfile 都是 rake 所需的文件,这个后面会讲到。
再者就是配置 gitlab-mirrors,教程很详细不再重复。

偷梁换柱

利用私有 Spec 仓库特性,可以把官方 Spec 目录下面的包按需或全部镜像过来,再次基础上把里面涉及 github 的地址替换成 gitlab 的地址

你没有看错,这是核心步骤,如果这步没有做那么和国内镜像的地址没有任何差别。核心代码如下:

Rakefile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
require 'uri'
require 'fileutils'
require 'multi_json'
require 'net/ssh'
desc '镜像一个 github 包至 gitlab 仓库'
task :clone, [:name] do |t, p|
  name = p[:name]
  current_path = Dir.pwd
  specs = Dir[File.join(File.expand_path('~'), '.cocoapods/repos/master/Specs/*')]
  repo = specs.select { |s| File.basename(s) == name }.first
  if repo
    puts " * found repo, copy it here"
    repo_store_path = File.join(current_path, 'Specs')
    FileUtils.cp_r repo, repo_store_path
    puts " * updating repo url"
    Dir["#{repo_store_path}/#{name}/*"].each do |f|
      pod_file = File.join(f, "#{name}.podspec.json")
      json = File.read(pod_file)
      data = MultiJson.load json
      if data['source']['git']
        puts " -> #{data['version']}: git"
        orginal_repo_url = data['source']['git']
        coverted_repo_name =  URI.parse(orginal_repo_url).path[1..-1].gsub('/''-').downcase
        data['source']['git'] = "http://gitlab.dev/mirrors/#{coverted_repo_name}"
        File.write(pod_file, JSON.pretty_generate(data))
      else data['source']['http']
        puts " -> #{data['version']}: http url, do you want speed up?"
      else data['source']['svn']
        puts " -> #{data['version']}: svn repo, do you want speed up?"
      end
    end
  else
    puts "Not find spec named: #{name}"
  end
end
desc 'gitlab 服务器镜像 Cocoapod Spec'
task :mirror, [:repo] do |t, p|
  host        = '172..0.1'
  user        = 'icyleaf'
  options     = {:keys => '~/.ssh/keys/id_rsa.pub'}
  puts "Connect gitlab server and mirror"
  Net::SSH.start(host, user, options) do |ssh|
    gitmirror_path = '/home/gitmirror/gitlab-mirrors'
    cmd = "sudo -u gitmirror -H rake \"add[#{p[:repo]}]\""
    stdout = ssh.exec!("echo 'cd #{gitmirror_path} && #{cmd}'")
    puts stdout
    ssh.loop
  end
end

Gemfile

1
2
3
4
5
gem 'rest_client'
gem 'multi_json'
gem 'rake'
gem 'net-ssh'

rake 里面有两个 task:

  • mirror: 镜像 iOS 开源组件

  • clone: 负责把官方 spec 指定包(开源组件的版本控制)替换 gitlab 地址并加入到私有包仓库

总结

通过工具总有办法可以改进和提升开发者的效率和解决各种的问题,希望本文可以给大家带来更多的灵感!

答疑解惑

F: 这套理论靠谱吗?

A: 目前我们团队已经采用并运行了很长一段时间,没有任何风险。最大的优势在于兼容官方的仓库,
就算无法链接自己的私有服务器,使用官方和国内镜像的都可以瞬间切换。

F: 如果没有服务器可以实现吗?

A: 醒醒吧孩子,就连单纯的镜像官方 Cocoapods Spec 还需要一个服务器执行定期同步脚本呢。

F: 国内 git 托管服务器能够支持吗?

A: 据我所知国内大部分 git 托管服务器的解决方案都是基于 gitlab 二次开发的,理论上可行,
上面提到的 gitlab-mirror 本身依赖于 gitlab 的 api 在镜像的同时自动新建仓库。如果有成功的欢迎反馈。

F: 我从你代码发现服务器同样调用了一个 rake 脚本,你没有开源!

A: 眼睛真够敏锐的,个人对 gitlab-mirror 再做镜像时做了一个约束,新建一个 Rakefile 文件放到你的 gitlab-mirror 项目根目录即可:

1
2
3
4
5
6
7
8
9
10
11
12
13
require 'uri'
desc "Adding repo to gitmirror"
task :add, [:repo] do |t, p|
  repo = p[:repo]
  begin
    name = URI.parse(repo).path[1..-1].gsub('/''-').gsub('.git''')
    if name
      `./add_mirror.sh -f --git --project-name #{name} --mirror #{repo}`
    end
  rescue Error => e
    puts 'not url'
  end
end

经验分享:极速化 CocoaPods的更多相关文章

  1. (转)CMOS Sensor的调试经验分享

    CMOS Sensor的调试经验分享 我这里要介绍的就是CMOS摄像头的一些调试经验. 首先,要认识CMOS摄像头的结构.我们通常拿到的是集成封装好的模组,一般由三个部分组成:镜头.感应器和图像信号处 ...

  2. CMOS Sensor的调试经验分享

    转自:http://bbs.52rd.com/forum.php?mod=viewthread&tid=276351 CMOS Sensor的调试经验分享 我这里要介绍的就是CMOS摄像头的一 ...

  3. CMOS Sensor的调试经验分享【转】

    转自:https://blog.csdn.net/yapingmcu/article/details/37817727 转自:http://bbs.52rd.com/forum.php?mod=vie ...

  4. Splunk大数据分析经验分享

    转自:http://www.freebuf.com/articles/database/123006.html Splunk大数据分析经验分享:从入门到夺门而逃 Porsche 2016-12-19 ...

  5. [2017-09-05]Abp系列——Abp后台作业系统介绍与经验分享

    本系列目录:Abp介绍和经验分享-目录 什么是后台作业系统 后台作业系统即BackgroundJob,从需求上讲,是一套基础设施,允许我们定义一个作业,在未来指定的某个时间去执行. 后台作业的一般场景 ...

  6. 【原创经验分享】WCF之消息队列

    最近都在鼓捣这个WCF,因为看到说WCF比WebService功能要强大许多,另外也看了一些公司的招聘信息,貌似一些中.高级的程序员招聘,都有提及到WCF这一块,所以,自己也关心关心一下,虽然目前工作 ...

  7. 【原创经验分享】JQuery(Ajax)调用WCF服务

    最近在学习这个WCF,由于刚开始学 不久,发现网上的一些WCF教程都比较简单,感觉功能跟WebService没什么特别大的区别,但是看网上的介绍,就说WCF比WebService牛逼多少多少,反正我刚 ...

  8. 关于启用 HTTPS 的一些经验分享(二)

    转载: 关于启用 HTTPS 的一些经验分享(二) 几天前,一位朋友问我:都说推荐用 Qualys SSL Labs 这个工具测试 SSL 安全性,为什么有些安全实力很强的大厂家评分也很低?我认为这个 ...

  9. 关于启用 HTTPS 的一些经验分享(一)

    转载: 关于启用 HTTPS 的一些经验分享(一) 随着国内网络环境的持续恶化,各种篡改和劫持层出不穷,越来越多的网站选择了全站 HTTPS.就在今天,免费提供证书服务的 Let's Encrypt ...

随机推荐

  1. React.js 小书介绍

    React.js 小书 Github 关于作者 这是一本关于 React.js 的小书. 因为工作中一直在使用 React.js,也一直以来想总结一下自己关于 React.js 的一些知识.经验.于是 ...

  2. 进入MVC处理通道

    这一篇主要讲如何通过Asp.net处理管道把请求交给MVC进行处理的(进入MVC处理通道). 首先来看一下经典的Asp.net处理管道的生命周期. 我们知道一个ASP.NET应用程序可以有多个Http ...

  3. 这可能是最low的发布dotnet core站点到centos7

    前言 不得不说:我在chrome上写了好长一段,贴了23张图,然后一个crash..我想说我电脑上的chrome已经crash太多次了 以后一定要搞离线编辑的. 正文 什么是.net core,bal ...

  4. 实现excel导入导出功能,excel导入数据到页面中,页面数据导出生成excel文件

    今天接到项目中的一个功能,要实现excel的导入,导出功能.这个看起来思路比较清楚,但是做起了就遇到了不少问题. 不过核心的问题,大家也不会遇到了.每个项目前台页面,以及数据填充方式都不一样,不过大多 ...

  5. HTML基本结构与标签总结整理篇

    HTML基本结构与标签总结整理篇 前言:这是笔者的学习总结与整理,如果有错误或疑问的地方,欢迎指正与讨论!另:此文会不定时更新~ 1.了解HTML 学习前端技术,必然涉及三个方面:html(结构).c ...

  6. Bootstrap table使用心得---thead与td无法对齐的问题

    当使用工具条中的显示/隐藏列的时候, 经常出现表格的列头与内容无法对齐的问题. 1. 去掉option中的height,完美对齐,但当数据较多的时候,table会自动增加height,显示所有数据而不 ...

  7. Egret index.html设置

    <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <title> ...

  8. php7.0版本不再以类名命名构造函数

    <?php class Car { var $color = "add"; function Car($color="green") { $this-&g ...

  9. PHP发送E-mail---新手教程

    首先下载PHPmailer拓展包,其实就是别人封装好的类库,下载链接:http://pan.baidu.com/s/1slbhGo1 首先去163注册个账号,然后登陆进去,点击设置下面的 POP3/S ...

  10. DotNetCore跨平台~文章索引~永久更新

    本索引目录主要包括仓储大叔对dotnet core架构的研究与知识积累,从2016年开始进行撰写,到今天已经有一年多了,其中有一些小知识,小技巧,小应用,希望给大家在开发时一些启发,也希望dotnet ...