解決CocoaPods慢的小技巧

weixin_34208283發表於2017-01-19

我們對CocoaPods的感情真是又愛又恨的,愛的是用它來管理第三方庫非常方便,恨的是每次需要更新一些第三方庫的時候,速度像蝸牛一樣慢。本篇文章分享幾個小技巧加快CocoaPods更新第三方庫的速度。

RubyGems換源

RubyGems是什麼呢?下面是官網給出的一段介紹:

The RubyGems software allows you to easily download, install, and use ruby software packages on your system. The software package is called a “gem” and contains a package Ruby application or library.

Gems can be used to extend or modify functionality in Ruby applications. Commonly they’re used to distribute reusable functionality that is shared with other Rubyists for use in their applications and libraries. Some gems provide command line utilities to help automate tasks and speed up your work.

通俗地來講RubyGems就像是一個倉庫,裡面包含了各種軟體的包(如Cocoapods、MySql),可以通過命令列的方式來安裝這些軟體包,最為方便的是自動幫你配置好軟體依賴的環境,整個安裝過程僅僅只需要幾行命令列。

我們在安裝CocoaPods的時候,就是通過rubygems來安裝的,由於在國內訪問rubygems非常慢,所以替換rubygems映象源就顯得十分必要了。在替換rubygems映象源的時候,先檢查一下rubygems的版本,建議在2.6.x以上,如果沒有的話,建議先升級一下,升級命令列如下:

$ gem update --system # 這裡請翻牆一下
$ gem -v
2.6.7

升級完成之後,可以用gem -v檢視下現在的版本號,比如我現在的版本是2.6.7。之前很多人用的都是淘寶的映象源,現在淘寶的rubygems映象源交給Ruby China來維護了,替換rubygems映象源的命令列如下:

$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -l
https://gems.ruby-china.org
# 確保只有 gems.ruby-china.org

這裡做一下說明,remove後面的映象源地址填寫你當前的映象源地址。比如你當前的映象源地址是淘寶的,命令列如下:

$ gem sources --add https://gems.ruby-china.org/ --remove http://ruby.taobao.org/

總結:替換rubygems的映象源,帶給我們的好處有兩點:

  • 安裝、更新CocoaPods的時候,速度更快,解決半天無反應的情況。
  • 安裝其他軟體也可以更加迅速,比如mysql等。

repo換源

使用CocoaPods的時候,經常要和這幾個命令列打交道:

pod install
pod update
pod repo update

每次執行這幾個命令的時候,真是一件痛苦的事情,等個半小時、一小時或者更長時間才能執行完,為什麼會出現這種現象呢?我們先來補充一些基礎知識:

當CocoaPods安裝成功以後,它預設的映象源地址是github(https://github.com/CocoaPods/Specs.git),開啟命令列進入到下面的檔案:

$ cd ~/.cocoapods/repos
$ ls
DDNPrivatePods              taobao-baichuansdk-alibcspecs
master                      taobao-baichuansdk-alibcspecsmirror

會看到有一個master的檔案,這就是CocoaPods在本地建立了一個master的repo,master裡面包含了所有第三方庫的地址列表,每一個庫的詳細資訊記錄在podspec檔案裡面。以為YTKNetwork例,我們看下podspec裡面包含的資訊:

{
    "name": "YTKNetwork",
    "version": "2.0.3",
    "summary": "YTKNetwork is a high level request util based on AFNetworking.",
    "homepage": "https://github.com/yuantiku/YTKNetwork",
    "license": "MIT",
    "authors": {
        "tangqiao": "tangqiao@fenbi.com",
        "lancy": "lancy@fenbi.com",
        "maojj": "maojj@fenbi.com",
        "liujl": "liujl@fenbi.com"
    },
    "source": {
        "git": "https://github.com/yuantiku/YTKNetwork.git",
        "tag": "2.0.3"
    },
    "source_files": "YTKNetwork/*.{h,m}",
    "requires_arc": true,
    "private_header_files": "YTKNetwork/YTKNetworkPrivate.h",
    "platforms": {
        "ios": "7.0",
        "osx": "10.9",
        "watchos": "2.0",
        "tvos": "9.0"
    },
    "frameworks": "CFNetwork",
    "dependencies": {
        "AFNetworking": [
            "~> 3.0"
        ]
    }
}

上面我們可以看出其指定了tag標籤、原始碼的下載地址,另外在YTKNetwork下有好多tag標籤,如下:

0.1.0 0.2.0 0.3.0 0.4.0 0.5.0 0.6.0 1.0.0 
1.1.0 1.2.0 1.3.0 2.0.0 2.0.1 2.0.2 2.0.3                               

至此我們瞭解master下面的一個庫大概包含哪些資訊,第一:指定了tag標籤、原始碼下載地址;第二:庫檔案目錄下包含了許多tag標籤,一個版本對應一個tag標籤。

瞭解完這些基礎知識以後,我們來分下一下pod update、pod install、pod repo update背後發生了什麼,導致其速度巨慢。分析問題的先決條件是你本地已經有一個master的repo。當你執行上面的命令列時,它們會把本地的repo所有地址列表更新一次,在這個過程中實際使用的是git fetch來執行的。為什麼是使用git fetch來執行的?下面一段話給出瞭解釋:

Git fetch is used because git clone will only download the history of the default branch (some info about the default branch of a bare repo is available here). As we can't know whether a given tag will be on the default branch or not, we need to fetch the whole repo (the cache) in our clone (the Pod checkout used for the installation).

簡單來說就是我們不知道給定的tag標籤是不是在預設的分支上面,所以不得不把全部repo給拉取下來做一下比較,才能確定給定的tag標籤是在哪個分支上面。我們通過一個例子來說明一下,master repo下有一個A庫,A庫在更新前本地有10個tag標籤,也就是有10個版本,CocoaPods要想檢測一下A庫有沒有最新的版本,它就去github上的repo地址列表拷貝一份A庫最新所有的tag標籤,和本地的tag標籤做一個比較,從而判斷A庫有沒有最新版本,需要不需要更新。

而git clone僅僅下載預設分支且預設分支repo的大小要比全部分支repo的大小小許多,還有最重要的一點是git clone明確了tag標籤是在預設分支上,這樣就不要下載全部的repo進行大量的比較了。

總結:

  • git fetch下載的repo要比git clone下載的repo大許多。
  • 給定一個tag標籤,git clone明確了一個庫的tag標籤在預設分支上,而git fetch則不能。
  • git fetch為了確定庫的標籤在哪個分支上需要做大量的計算,而git clone則不需要。

我們可以看出git clone要比git fetch快許多,所以要在使用cocoapods時要儘量避免執行git fetch,看下下面幾種解決方案:

方案一: 使用下面兩個命令列

pod installl --no-repo-update --verbose
pod update --no-repo-update --verbose

其中--verbose的作用就是列印出執行過程中詳細的資訊,--no-repo-update的作用就是禁止更新repo,這樣就避免執行了git fetch,從而加快速度。但是如果repo本身就很老(第三方庫版本比較低)的時候,仍然是需要更新repo的,這種情況下如何處理呢?請看方案二和方案三。

**方案二: **進入到repos目錄下,通過git clone直接新增master庫,命令列如下:

$ cd ~/.cocoapods/repos 
$ pod repo remove master
$ git clone https://github.com/CocoaPods/Specs.git master

首先要把本地老的master分支給移除掉,然後使用git clone從github映象源上clone一份且設定本地master庫。這樣本地的repo就是最新的了,此時在進入到當前工程目錄下,執行方案一提供的命令列。這樣就解決了工程依賴的第三方庫版本過低需要更新的問題。但是我們在clone github映象源的時候,發現速度還是比較慢的,這是因為國內訪問github的速度不給力,沒辦法的事情,這個時候可以考慮掛一個VPN或者使用國內一些網站提供的映象源。

方案三:repo換源

方案三就是為了解決方案二出現clone github映象源比較慢的問題,可以換成coding提供的一個映象源,命令列如下:

$ cd ~/.cocoapods/repos 
$ pod repo remove master
$ git clone https://git.coding.net/hging/Specs.git master

這樣在clone的時候會發現速度很快哈。另外,在自己工程中的Podfile檔案加入下面一行描述:

source 'https://git.coding.net/hging/Specs.git'

如果不加這一句話,它預設還是從github映象源地址去下載的,這個不要給忘記了。

注意點:

  • master repo裡面存放的是所有第三方庫的地址列表,下載第三方庫對應的原始碼還是要到指定的原始碼存放地址(podspecs中有指定)去下載。更換repo源只是加快了repo的下載速度,並不會加快第三方庫原始碼的下載速度,兩者是沒有任何關係的。
  • 在工程中儘量避免直接使用pod update、pod install,在後面新增--no-repo-update後使用。
  • 工程中依賴第三方庫版本過低,可以先到repos目錄下,使用git clone更新master repo,然後在工程中使用pod update --no-repo-update命令。

上面提到的三種方案從一定程度上加快了CocoaPods的執行速度,但是仍然避免不了要更新全部repo的情況,而實際情況是我們專案當中用到的第三方庫大部分只需要十幾個,大量的時間被浪費在我們不需要的庫上面了。因為CocoaPods是使用中心化的方式來進行管理的,所以當第三方庫多起來的時候,就會出現剛才的情況,這個時候可以選擇使用Carthage來管理第三方庫,它比CocoaPods最大的優勢就在於去中心化的方式來管理,不過Carthage的缺點是裡面的庫還不是很豐富,不過隨著時間的推移就不是問題了。

總結

在第一次安裝CocoaPods的時候,替換成rubychina提供的rubygems映象倉庫。在實際工程中儘量避免讓CocoaPods執行git fetch命令,比如執行pod update、pod install、pod repo udpate等命令都會引起CocoaPods執行git fetch命令。

參考文章:
https://github.com/CocoaPods/CocoaPods/issues/1077
http://hyichao.github.io/ios/2015/12/06/cocoapods-slow.html
https://mirrors.tuna.tsinghua.edu.cn/help/CocoaPods/
http://gems.ruby-china.org/

國士梅花

歡迎大家關注國士梅花,技術路上與你陪伴。

416556-34d2366fbc81b9be.jpg
guoshimeihua.jpg

相關文章