使用 jsdelivr 加速 cocoapod 库

文章目录

iOS 开发时, cocoapods(后简称 pod) 是很常用的工具

我们偶尔也会自己开发 pod 库并上传到 pod 上

pod 的源码支持多种来源, 本地 path git http 等

一般来说, 如果是纯开源库, 我们直接把源码上传到 github , 然后使用 git 依赖即可

但是这有一个问题, github 的速度在中国大陆并不快, 我们有没有办法加速它呢?

这时候经过搜索, jsdelivr 出现在了搜索引擎里, 号称国内外都可用的 cdn, 我用 wget 测试了一下, 国内外都可以保证 10M+/s 的速度

jsdelivr 介绍

这东西本身最初目的是为了加速 js/css 的访问

但是, 上面也说了, 支持"任何"在 github 上的仓库, 很好, 我就喜欢这样的东西

版本号的坑

文档上说支持所有 ref 作为版本号, 然而不是, 我这里测试只支持 tag/release

包体大小限制

我的目的是为了给 flutter_ijkplayer 的 iOS 仓库找一个下载地址, ijkplayer 的 iOS 部分很大, 我打包完有 150M, 用了 xz 压缩方案让包变成了 35M

但 jsdelivr 有两个限制: 单文件不能大于 20M, 仓库的某版本不能大于 50M, 那这里就有问题了, 我的 xz 是 35M, 超过限制了, 这里我就要找解决方案了

解决之路

思考

首先是分拆, 这个好说, macOS 的 split 命令就支持

那合并呢? cat 命令就可以了

但怎么在 pod 中做呢, 我搜了一下 podspec 的语法, 发现可以配置 prepare_command 参数, 这个参数在安装时会被使用, 并且使用完毕后才会校验库是否存在

我们可以在这一步中来做真实的下载和合并操作

有了完整思路, 我要开始着手实施了

发包

前提: 假设我本地有一个 framework.tar.xz, 这个是已经打包好的库文件

分割文件

1split -b 10m IJKMediaFramework.tar.xz IJKMediaFramework.tar.xz.

这里要注意最后一个参数最后有一个. 这样就能完成拆分

1ll IJKMediaFramework.tar.xz*
2-rw-r--r--  1 caijinglong  staff    33M  3 18 11:34 IJKMediaFramework.tar.xz
3-rw-r--r--  1 caijinglong  staff    10M  3 18 11:34 IJKMediaFramework.tar.xz.aa
4-rw-r--r--  1 caijinglong  staff    10M  3 18 11:34 IJKMediaFramework.tar.xz.ab
5-rw-r--r--  1 caijinglong  staff    10M  3 18 11:34 IJKMediaFramework.tar.xz.ac
6-rw-r--r--  1 caijinglong  staff   3.0M  3 18 11:34 IJKMediaFramework.tar.xz.ad

测试一下合并

1cat IJKMediaFramework.tar.xz.* > IJKMediaFramework-Test.tar.xz
2
3ll IJKMediaFramework-Test.tar.xz
4-rw-r--r--  1 caijinglong  staff    33M  3 18 13:58 IJKMediaFramework-Test.tar.xz

这里大小是 ok 的. 再解压一下试试

 1mkdir test
 2mv IJKMediaFramework-Test.tar.xz test
 3cd test
 4tar xvf IJKMediaFramework-Test.tar.xz
 5
 6
 7ll
 8drwxr-xr-x  7 caijinglong  staff   224B  3 18 11:33 IJKMediaFramework.framework
 9-rw-r--r--  1 caijinglong  staff   1.0K  3 18 11:33 LICENSE
10
11ll IJKMediaFramework.framework
12total 295944
13drwxr-xr-x  14 caijinglong  staff   448B  3 18 11:33 Headers
14-rw-r--r--   1 caijinglong  staff   130M  3 18 11:33 IJKMediaFramework
15-rw-r--r--   1 caijinglong  staff   757B  3 18 11:33 Info.plist
16drwxr-xr-x   3 caijinglong  staff    96B  3 18 11:33 Modules
17drwxr-xr-x   4 caijinglong  staff   128B  3 18 11:33 libyuv

解压缩也成功了, 接着就是编写脚本了

合并脚本

我创建了一个 cat.sh 脚本

1wget https://cdn.jsdelivr.net/gh/CaiJingLong/flutter_ijkplayer_pod_spliter@0.2.2/IJKMediaFramework.tar.xz.aa
2wget https://cdn.jsdelivr.net/gh/CaiJingLong/flutter_ijkplayer_pod_spliter@0.2.2/IJKMediaFramework.tar.xz.ab
3wget https://cdn.jsdelivr.net/gh/CaiJingLong/flutter_ijkplayer_pod_spliter@0.2.2/IJKMediaFramework.tar.xz.ac
4wget https://cdn.jsdelivr.net/gh/CaiJingLong/flutter_ijkplayer_pod_spliter@0.2.2/IJKMediaFramework.tar.xz.ad
5cat IJKMediaFramework.tar.xz.* > IJKMediaFramework.tar.xz
6tar xvf IJKMediaFramework.tar.xz
7rm IJKMediaFramework.tar.xz.* IJKMediaFramework.tar.xz

这个脚本会完成下载, 连接, 解压, 删除压缩包的过程, 这样剩余的就是干净的文件了, 只包含 Framework LICENSE README

上传 github

这里根据你自己的情况选择上传方式, 我是用的 python 脚本配合 github 的 rest v3 api 上传的, 你可以用 git 或者 gihtub 的网页端 接着有一步很重要的步骤, release 这个版本, 不然 jsdelivr 找不到

我的脚本地址: 需要配置两个环境变量 一个是版本号 一个是 GITHUB_TOKEN, 当然如果想要用的话, 还是需要其他修改的, 比如仓库名, 拥有者名等等信息

podspec

 1Pod::Spec.new do |spec|
 2
 3  version = "0.2.2"
 4  spec.name         = "FlutterIJK"
 5  spec.version      = "#{version}"
 6  spec.summary      = "IJKPlayer for Flutter."
 7  spec.description  = <<-DESC
 8  IJKPlayer for flutter
 9                   DESC
10
11  spec.homepage     = "https://github.com/CaiJingLong/flutter_ijkplayer_pod"
12  spec.license      = { :type => 'MIT', :file =>'LICENSE' }
13  spec.author             = { "Caijinglong" => "cjl_spy@163.com" }
14  spec.source       = { :http => "https://cdn.jsdelivr.net/gh/CaiJingLong/flutter_ijkplayer_pod_spliter@#{version}/README.tar.gz"}
15  spec.vendored_frameworks = 'IJKMediaFramework.framework'
16  spec.frameworks  = "AudioToolbox", "AVFoundation", "CoreGraphics", "CoreMedia", "CoreVideo", "MobileCoreServices", "OpenGLES", "QuartzCore", "VideoToolbox", "Foundation", "UIKit", "MediaPlayer"
17  spec.libraries   = "bz2", "z", "stdc++"
18
19  spec.platform = :ios
20  spec.ios.deployment_target = '8.0'
21  spec.requires_arc = true
22
23  spec.prepare_command = <<-CMD
24    sh cat.sh
25  CMD
26end

这样在 pod install 的过程中会完成如下步骤

  1. 下载 https://cdn.jsdelivr.net/gh/CaiJingLong/flutter_ijkplayer_pod_spliter@#{version}/README.tar.gz 文件 version 是字符串插值的版本号
  2. pod 会帮我们解压这个 gz
  3. 运行 gz 中的 cat.sh 脚本来完成下载, 合并, 删除多余文件的操作

trunk, 也就是上传的信息:

 1Updating spec repo `trunk`
 2  CDN: trunk Relative path: deprecated_podspecs.txt modified during this run! Returning local
 3  CDN: trunk Going to update 15 files
 4  CDN: trunk Relative path: all_pods_versions_1_1_5.txt modified during this run! Returning local
 5  CDN: trunk Relative path: all_pods_versions_4_9_1.txt modified during this run! Returning local
 6  CDN: trunk Relative path: all_pods_versions_1_1_7.txt modified during this run! Returning local
 7  CDN: trunk Relative path: all_pods_versions_5_d_c.txt modified during this run! Returning local
 8  CDN: trunk Relative path: AlgoliaSearch.yml modified during this run! Returning local
 9  CDN: trunk Relative path: all_pods_versions_e_9_d.txt modified during this run! Returning local
10  CDN: trunk Relative path: all_pods_versions_2_1_1.txt modified during this run! Returning local
11  CDN: trunk Relative path: CocoaPods-version.yml modified during this run! Returning local
12  CDN: trunk Relative path: all_pods_versions_7_f_a.txt modified during this run! Returning local
13  CDN: trunk Relative path: all_pods_versions_d_6_9.txt modified during this run! Returning local
14  CDN: trunk Relative path: all_pods_versions_6_0_4.txt modified during this run! Returning local
15  CDN: trunk Relative path: all_pods_versions_f_4_e.txt modified during this run! Returning local
16  CDN: trunk Relative path: all_pods_versions_8_d_3.txt modified during this run! Returning local
17  CDN: trunk Relative path: all_pods_versions_1_9_2.txt modified during this run! Returning local
18  CDN: trunk Relative path: all_pods_versions_c_e_7.txt modified during this run! Returning local
19  - Data URL: https://raw.githubusercontent.com/CocoaPods/Specs/48458c6e0cf376dcb2c374f6b349b960fefa883c/Specs/4/9/1/FlutterIJK/0.2.2/FlutterIJK.podspec.json
20  - Log messages:
21    - March 17th, 21:06: Push for `FlutterIJK 0.2.2' initiated.
22    - March 17th, 21:06: Push for `FlutterIJK 0.2.2' has been pushed (0.922508893 s).

这样就完成了发包的全过程

组织结构

下面是发包时的目录结构

 1tree output/
 2output/
 3├── IJKMediaFramework.framework
 4│   ├── Headers
 5│   │   ├── IJKAVMoviePlayerController.h
 6│   │   ├── IJKFFMonitor.h
 7│   │   ├── IJKFFMoviePlayerController.h
 8│   │   ├── IJKFFOptions.h
 9│   │   ├── IJKKVOController.h
10│   │   ├── IJKMPMoviePlayerController.h
11│   │   ├── IJKMediaFramework.h
12│   │   ├── IJKMediaModule.h
13│   │   ├── IJKMediaPlayback.h
14│   │   ├── IJKMediaPlayer.h
15│   │   ├── IJKNotificationManager.h
16│   │   └── IJKSDLGLViewProtocol.h
17│   ├── IJKMediaFramework
18│   ├── Info.plist
19│   ├── Modules
20│   │   └── module.modulemap
21│   └── libyuv
22│       ├── include
23│       │   ├── libyuv
24│       │   │   ├── basic_types.h
25│       │   │   ├── compare.h
26│       │   │   ├── compare_row.h
27│       │   │   ├── convert.h
28│       │   │   ├── convert_argb.h
29│       │   │   ├── convert_from.h
30│       │   │   ├── convert_from_argb.h
31│       │   │   ├── cpu_id.h
32│       │   │   ├── macros_msa.h
33│       │   │   ├── mjpeg_decoder.h
34│       │   │   ├── planar_functions.h
35│       │   │   ├── rotate.h
36│       │   │   ├── rotate_argb.h
37│       │   │   ├── rotate_row.h
38│       │   │   ├── row.h
39│       │   │   ├── scale.h
40│       │   │   ├── scale_argb.h
41│       │   │   ├── scale_row.h
42│       │   │   ├── version.h
43│       │   │   └── video_common.h
44│       │   └── libyuv.h
45│       └── lib
46│           └── libyuv.a
47├── IJKMediaFramework.tar.xz
48├── IJKMediaFramework.tar.xz.aa
49├── IJKMediaFramework.tar.xz.ab
50├── IJKMediaFramework.tar.xz.ac
51├── IJKMediaFramework.tar.xz.ad
52├── LICENSE
53├── README.md
54├── README.tar.gz
55├── cat.sh
56└── files

lipo 脚本

另外, 我的项目中, 我还编写了一个 lipo 脚本, 用于合并产物, 分割文件, 调用上传的 python

后记

本篇没有单独的仓库, 但是可以参考 来作为入口看整个过程

以上