检查gem发布包尺寸的指南

144 阅读6分钟

大多数宝石可能最多只有几百kb。我说的是实际存储在Rubygems中并由使用该宝石的应用程序从Rubygems下载的软件包。

毕竟,源代码只是文本,它不会占用太多的空间。好吧,也许有些 gem 里面有几张图片。

但是,如果你在 rubygems 中查看你的 gem,发现它有 10MB 或更大......而且似乎每个版本都在变大......可能有什么问题,值得研究一下。

研究它的一个方法是看一下实际的 gem 包。如果你使用方便的bundler rake任务来发布你的gem(我推荐这样做),你在你最后发布的源码中有一个./pkg 目录。里面有你从那里发布的每个版本的".gem "文件,除非你最近清理了它。

事实证明,.gem文件只是.tar文件。 这里面有更多的tar和gz文件等等。我们可以进入其中,提取内容,并使用方便的unix工具du -sh ,看看是什么占用了所有的空间。

我是如何找到这些字节的

jrochkind-chf kithe (master ?) $ cd pkg

jrochkind-chf pkg (master ?) $ ls
kithe-2.0.0.beta1.gem        kithe-2.0.0.pre.rc1.gem
kithe-2.0.0.gem            kithe-2.0.1.gem
kithe-2.0.0.pre.beta1.gem    kithe-2.0.2.gem

jrochkind-chf pkg (master ?) $ mkdir exploded

jrochkind-chf pkg (master ?) $ cp kithe-2.0.0.gem exploded/kithe-2.0.0.tar

jrochkind-chf pkg (master ?) $ cd exploded

jrochkind-chf exploded (master ?) $ tar -xvf kithe-2.0.0.tar
 x metadata.gz
 x data.tar.gz
 x checksums.yaml.gz

jrochkind-chf exploded (master ?) $  mkdir unpacked_data_tar

jrochkind-chf exploded (master ?) $ tar -xvf data.tar.gz -C unpacked_data_tar/

jrochkind-chf exploded (master ?) $ cd unpacked_data_tar/
/Users/jrochkind/code/kithe/pkg/exploded/unpacked_data_tar

jrochkind-chf unpacked_data_tar (master ?) $ du -sh *
 4.0K    MIT-LICENSE
  12K    README.md
 4.0K    Rakefile
 160K    app
 8.0K    config
  32K    db
 100K    lib
 300M    spec

jrochkind-chf unpacked_data_tar (master ?) $ cd spec

jrochkind-chf spec (master ?) $ du -sh *
 8.0K    derivative_transformers
 300M    dummy
  12K    factories
  24K    indexing
  72K    models
 4.0K    rails_helper.rb
  44K    shrine
  12K    simple_form_enhancements
 8.0K    spec_helper.rb
 188K    test_support
 4.0K    validators

jrochkind-chf spec (master ?) $ cd dummy/

jrochkind-chf dummy (master ?) $ du -sh *
 4.0K    Rakefile
  56K    app
  24K    bin
 124K    config
 4.0K    config.ru
 8.0K    db
 300M    log
 4.0K    package.json
  12K    public
 4.0K    tmp

糟了!在这个特定的 gem 中,我有一个假的 rails 应用程序,它有 300MB 的日志,因为我已经有一段时间没有修剪它们了,这些日志最终包括在分发给 rubygems 并被所有消费者下载的 gem 发布包中 即使它们很小,我也不希望这些东西出现在发布的gem包里!这可不好!"。

这可不好! 它只变成了12MB而不是300MB,因为日志文件是如此的可压缩,而且在组装rubygems包时也涉及到压缩。但我不知道它在消耗应用程序的机器上实际占用了多少空间。这是很不负责任的!

是什么在控制哪些文件被包含在 gem 包中?

当然是你的.gemspec文件。s.files = 这一行是一个数组,包含了要包含在gem包中的每个文件。此外,s.test_files 是另一个包含更多文件的数组,这些文件不应该是运行 gem 所必须的,而是用来测试它的。

(Rubygems的建立是为了允许在下载后对宝石进行自动*测试,这就是为什么测试文件包含在发布包中。我不确定这有多大用处,如果有人这样做的话,又有谁会这样做;尽管我相信一些Linux发行版的打包者试图利用它,无论好坏)。

但没有人愿意单独列出你的gem中的每一个文件,在你每次添加、删除或移动一个文件时手动编辑阵列。幸运的是,gemspec文件是可执行的ruby代码,所以你可以用ruby作为捷径。

我见过两种主要的方法,不同的 "gem skeleton生成器 "采取两种方法中的一种。

有时会使用shell out to git--其想法是,你在git中检查过的所有东西都应该在gem发布包中,不多也不少。例如,我的一个 gem 里面有这个,不知道它是从哪里来的,或者是谁/谁生成的。

spec.files = `git ls-files -z`.split("\x0").reject do |f| f.match(%r{^(test|spec|features)/}) end

在这种情况下,它不会在./spec中已经包含任何东西,所以这显然不是我们之前看的那个 gem。

但在这种情况下,除了使用ruby逻辑来处理结果外,被你的.gitignore 文件排除的东西最终都会包含在你的gem包中,太好了

在我们之前看的kithe ,那些日志文件.gitignore中(它们不在我的 repo中!),所以如果我一直使用那个git-shellout技术,它们就不会已经包含在ruby发布的版本中了。

但是......我没有。相反,这个 gem 有一个 gemspec,看起来像:

s.test_files = Dir["spec/*

只要在test_files列表中包括./spec 里面的每一个文件。哎呀。然后我就得到了所有这些日志文件!

一个解决的方法

我真的不知道git-shellout方法和dir-glob方法哪个更好。我怀疑这是rubydom历史上宗教战争的主题,当时还有更多的人在争论这种事情。有什么意见吗?或者另一种方法?

我没有心情去重组这个gemspec,我只是做了最简单的事情来阻止那些日志文件......

Dir["spec/*

用bundler提供的方便的rake build 任务在不发布的情况下构建软件包......这样我的gem发布包的大小就从12MB变成了64K。(这实际上听起来像是一个最小块大小或什么的,对吗?)

咻!这是一个很大的区别!我的GEM发布包从12MB变成了64K。这是一个很大的区别!对于那些使用以前的版本并最终下载了所有这些垃圾的人来说,我感到很抱歉(事实上,这个特殊的宝石在这一点上主要是一个概念证明,我不认为有其他人在使用它)。

检查你的创业板尺寸!

我愿意相信,有很多已发布的宝石都有像这样严重臃肿的发布包。这已经不是我第一次意识到是我的错了。因为谁会注意宝石的大小呢?显然,没有多少人!但rubygems确实列出了它们。

但rubygems确实列出了它们,所以很容易看到。你的宝石发布包是多兆的吗,而它们并没有很好的理由? 它们是否每次发布都会变大,远远超过你所认为的增加的代码行的字节数?在gem历史上的某个时刻,是否有一个从数百KB到多MB的大跳跃? 当gem的逻辑没有发生什么特别的变化来导致这种情况的时候?

所有这些都暗示着你可能包含了一些你并不想包含的东西,可能这些东西在每个版本中都在增长。

你不需要在你的 repo 中有一个假的 rails 应用程序来意外地做到这一点(我曾经在一个与 rails 无关的 gem 上意外地做到这一点)。也可能有其他类型的日志文件。或测试覆盖率或性能指标文件,或任何其他构建或开发的工件,特别是那些随着时间推移而增长的文件--这些文件实际上并不打算或不需要作为 gem 发布包的一部分

偶尔检查一下你的gem发布包是件好事。 在大多数情况下,你的gem发布包最多只能有几百KB,而不是几MB。帮助您的用户保持更快的安装和构建速度,使其更轻巧