说起Warble这个东西,好多人一听名字就头大,觉得这玩意儿就是来折腾人的。我刚接触它那会儿也是一样,每次想打包个应用上传到服务器,那个过程简直是噩梦,各种报错,各种找不到文件,搞得我焦头烂额的。但是后来我静下心来研究了一下,发现它就是个工具,用顺手了,那效率简直不要太高。
我记得最开始我就是照着网上的教程一步步来的,那个时候的需求特别简单,就是把一个Rails应用打包成一个可以部署的Gem包,然后放到线上跑起来。我那时候就盯着那个文件猛看。
第一次尝试:迷茫与抓瞎
我最开始就是把Gemfile里的依赖都写上去,然后直接跑warble executable这个命令。结果?程序跑起来了,但是一访问就报错,不是找不到asset,就是数据库连接不上。我当时把日志翻了个底朝天,感觉啥都写了,但就是跑不起来。
后来才发现,Warble打包的时候,默认只打包你代码里明确引用的东西,那些动态加载的或者在代码里不是硬编码引用的文件,它很容易就漏掉。我赶紧回过头来对着项目结构一个一个比对,看看哪些文件是我不能少的。

技巧一:精准控制打包内容
我最常用的一个技巧就是使用这个配置项。我把这个东西单独拉出来,列出一个非常详细的清单。比如我需要在View目录下放一些额外的配置文件,或者assets里有一些第三方库需要手动加入的CSS和JS,我就得在gemspec里明确指定它们的位置。
- 我创建一个
config/*文件,专门放这些自定义配置。 - 然后在里面写上
Warble::* do c。 - 我开始用
* += [...]来追加我需要的路径。比如我需要一个叫extra_*的文件,我就会写"config/extra_*"。
这样一来,Warble打包的时候就不会漏掉我想要的那些“犄角旮旯”里的文件了。
技巧二:处理依赖的尴尬
另一个让我头疼的是Gem依赖问题。Warble打包的时候,它只会把Gemfile里声明的Gem打包进去,但如果这个Gem又有它自己的依赖,Warble默认不会帮你把这些二级依赖也打包进来。这就导致应用跑起来后,一调用依赖Gem的功能就报错。
我的解决办法是,对于那些特别重要的,或者我确定服务器环境里可能没有安装的依赖,我强制用* = [...]把它们都列出来。这样打包出来的包里就包含了这些依赖的源代码或者预编译版本,大大降低了部署环境的复杂度。

如果服务器环境很稳定,依赖的库也都能通过系统包管理器安装,我也会选择在里写上一些部署脚本,让Warble在部署后自动执行安装依赖的命令,比如bundle install。
技巧三:定制启动脚本
一点就是启动脚本。默认的启动脚本有时候不太好使,特别是当你需要做一些预处理的时候,比如数据库迁移或者缓存预热。
我通常会覆盖掉默认的启动命令。我在里设置* = "my_app",然后我会定制* = "start_*"。这个start_*就是我自己写的一个小Shell脚本,里面先执行bundle exec rake db:migrate,确认数据库没问题后,再启动真正的应用服务器。
把这些配置搞定后,我再运行warble war,打包出来的文件体积大了点,但是部署起来就顺畅多了,基本上一劳永逸。现在我再也不怕Warble了,它成了我快速部署的利器。









