部署 记一次部署时出现 CSS FingerPrint 不一致的问题

jicheng1014 · 2019年03月26日 · 最后由 tanhui2333 回复于 2019年03月28日 · 1103 次阅读
本帖已被设为精华帖!

以前一直是前后端分离, 最近实在是受不了react 和 rails api 切来切去的人格分裂, 于是退回到 rails 渲染 前端

说实在的, 在页面不复杂的情况下 ( 小型内部用邮件, 短信,身份核验管理 ),套一个 bootstrap sb2 admin 的模板, turbolinks + SRJ, 比折腾 antd 强很多

很快开发就结束了, 就只剩下部署.

我的部署机器是这样规划的: 有两台机器 club_001 和 club_002 001 有公网IP, 002 没有, 同时002 的性能剩余稍多

我的这个小项目就打算部署到 002 上, 之后由于 002 上是没有装 nginx 的, 直接由 001 upstream 过来

这里遇到了第一个麻烦之处:

由于 nginx 是装在 001 上的, 而项目在 002 上, 所以 002 生成的静态文件, 是没有办法直接被 nginx 访问到的

(下面常规的nginx 配置是有问题的, 因为nginx 无法访问到 002 的 /var/www/tube_center/current/public)

server {
listen 80;
  listen 443 ssl;

  ssl_certificate /root/.acme.sh/cer;
  ssl_certificate_key /root/.acme.sh/key;
  server_name tubecenter.xxxxx.com;
  root /var/www/tube_center/current/public;
  try_files $uri/index.html $uri @puma_tubecenter_production;


  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  location @puma_tubecenter_production {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    proxy_redirect off;
    proxy_pass http://puma_tubecenter_production;
  }

  if ($request_method !~ ^(GET|HEAD|PUT|PATCH|POST|DELETE|OPTIONS)$ ){
    return 405;
  }
}

怎么解决? 最简单的 就是在cap 的 assets:compile after 加上脚本进行拷贝, 只不过因为要改deploy , 遂放弃

我选择了另一种方案, 就是在001 也部署这个项目, 但是这个项目仅仅只做precompile就好了, 以后万一需要也负载到001号机器, 也修改最少

于是, 修改deploy.rb 文件

server "club-api001",  roles: %w{web}
server "club-api002",  roles: %w{web app db}

默认 web 会生成 assets, puma 会运行在 app 上

之后执行 cap production deploy

一切正常, 但是访问的时候, 出现了问题

css 加载不出来,

我看源码, 编译正常 css 和 js 都有 fingerprint, 而且 js 的竟然还能访问,

于是我登录两台机器查看究竟,

发现两台机器编译出来的 css fingerprint, 竟然不一致

同时, 我又发现另外一个我自己写的devise.css 的是一致的,

所以推论得出 scss 应该工作的是正常的,

那么问题就出在了 application.css

cat 这两个文件, 格式化 放到 text differ 进行对比, 发现了一个有意思的地方

看起来似乎是循环下的随机数, 于是以css class name 为搜索条件, 去搜索 发现了一个 sb2 admin template 留给我的惊喜

// _error.scss

@keyframes noise-anim {
  $steps: 20;
  @for $i from 0 through $steps {
    #{percentage($i*(1/$steps))} {
      clip: rect(random(100)+px,9999px,random(100)+px,0);
    }
  }
}

这里看到 有一个叫做 random 的函数

在此最终找到原因

scss 在编译的时候, 由于使用了随机数, 导致了每次编译的 css 文件都 不一样, 所以 css 的最终内容不一致 所以 在002 号的puma 就找不到001 里和自己生成的assets 一样的文件

解决的办法也很简单, 就把random 函数去掉, 用固定值即可

最后在重新编译的时候并未发现assets 里的文件变化, 于是修改 initializers/assets.rb 文件里的

Rails.application.config.assets.version = '2.1'  # 新编号

即可重新编译 assets

至此, css 的 fingerprint 不一致的问题 就这样解决了.

其实实际中解决的比较着急, 因为太久没有做 rails 的前端了, 很多地方都在瞎猜, 搞了很多 对比环境的工作, 打docker 什么的, 方向走的不对

最后总结下:

  1. 相信科学, 不要瞎猜. 分析问题, 先易后难, 先大概率, 再小概率
  2. 在引入别人的内容时, 需要小心谨慎
  3. 如无必要, 不要在sass 里用 random
共收到 9 条回复

虽然我不用cap,但是cap好像有mirror

有意思。

pynix 回复

在官网上没找到相关内容呢 这个我还真不是太了解

追根溯源地解决问题是最有成就感的事情。

取巧就是修改 public/assets/.sprockets-manifest 这个隐藏文件

hooopo 将本帖设为了精华贴 03月28日 12:29

厉害😄

stargwq 回复

感谢刘老板赐教

@Rei 确实不错

@tanhui2333 不过其他的比较ok

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册