分享 2.5 个人如何开发一款跨终端的产品?[Ruby Tuesday 的分享]

zfben for 简单心理 · September 09, 2015 · Last by foru replied at October 20, 2015 · 18865 hits
Topic has been selected as the excellent topic by the admin.

Keynote 在这里(需要翻墙): https://speakerdeck.com/benz303/2-dot-5-ge-ren-ru-he-kai-fa-kuan-kua-zhong-duan-de-chan-pin

不看 Keynote 也没关系,我会具体说下我们公司(简单心理)如何在仅有 2.5 个人的情况下,基于 RoR 开发出了涵盖几乎全部常用终端的产品。

2.5 个人?

  • 1 个全栈(我 ^_^)
  • 1 个 Ruby 程序员
  • 0.5 个前端开发(产品经理兼职)

跨终端?

  • 电脑:浏览器、微信 PC 版(PC 版微信支持微信登陆)
  • 平板:浏览器、App(Android & iOS)、微信
  • 手机:浏览器、App(Android & iOS)、微信

这些终端不仅用于访问,还需要支持推送和支付:

  • 通知渠道:邮件、短信、微信、App 推送
  • 支付渠道:支付宝、微信支付、银联支付

解决方案

  • 尽可能降低开发工作量(人员有限)
  • 尽可能利用 RoR 已有技术
  • 基于 User Agent 信息来区分具体终端

从 RoR 出发

  • 使用 Turbolinks 优化网页加载体验
  • 不使用前端 MVC 框架加重工作量
  • 使用响应式设计 + 部分页面 Variant Response
  • 不针对各个终端单独制作页面

基于 browser 区分终端

  • browser 的双重含义:浏览器 和 browser gem
  • 每个终端都有各自的 User Agent
  • 通过扩展 browser gem 来判断当前的终端类型
  • 通过打印终端类型到 body class 使得 CSS 可以针对性调整样式

具体步骤

1. 使用并扩展 browser gem 来判断终端类型

Browser::NAMES[:smileback] = 'SmileBack' # 我们 App 的自定义 User Agent 标识
Browser::NAMES[:wechat] = 'Wechat'
Browser::NAMES[:desktop] = 'Desktop'

class Browser
  module Meta
    class Smileback < Base
      def meta
        'smileback' if browser.smileback?
      end
    end

    class Wechat < Base
      def meta
        'wechat' if browser.wechat?
      end
    end

    class Desktop < Base
      def meta
        'desktop' if browser.desktop?
      end
    end
  end

  module Consoles
    def smileback?
      !(ua =~ /smileback/i).nil?
    end

    def wechat?
      !(ua =~ /MicroMessenger/i).nil?
    end

    def desktop?
      !mobile? && !wechat? && !smileback?
    end
  end
end

2. 在 html body class 里添加 browser 信息,方便 CSS 套用

<body class="<%= Browser.new(ua: request.env['HTTP_USER_AGENT']).to_s %>"> <!-- class 会输出如 chrome modern mac webkit desktop 或 iphone ios mobile modern other safari safari5 webkit --!>
body{ /* 默认的样式 */ }
body.desktop{ /* 桌面浏览器定制样式 */ }
body.mobile{ /* 手机浏览器定制样式 */ }
body.wechat{ /* 微信定制样式 */ }

3. 使用 Variant Response 来针对部分区别大的页面做两套或多套 views

# application_controller.rb

before_action :detect_browser

private

def detect_browser
  request.variant = :mobile if Browser.new(ua: request.env['HTTP_USER_AGENT']).mobile?
end

需要拆分的页面,做成如下形式:

app/views/pages/home.erb
app/views/pages/home.html+mobile.erb # 文件名格式为 响应格式+设备名

4. 添加 helper,方便复杂的情况下调用,比如支付

# application_helper.rb

def browser
  @_browser ||= Browser.new(ua: request.env['HTTP_USER_AGENT'])
end
/ 懒得转 erb 格式了,下面这段是 slim 格式的
- if browser.smileback?
  a.button href="jdxlsmileback://recharges/#{resource.id}/pay" 支付宝付款
  = link_to '银联付款', pay_recharge_path(resource, unionpay: true), 'data-no-turbolink' => true
- elsif browser.wechat?
  - if current_user.weixin_id
    = link_to '微信支付', '#', id: 'wepay', class: 'button'
    = link_to '银联付款', pay_recharge_path(resource, unionpay: true), 'data-no-turbolink' => true
  - else
    = link_to '银联付款', pay_recharge_path(resource, unionpay: true), 'data-no-turbolink' => true, class: 'button'
- elsif browser.mobile?
  = link_to '支付宝付款', pay_recharge_path(resource, alipay: true), class: 'button', 'data-no-turbolink' => true
  = link_to '银联付款', pay_recharge_path(resource, unionpay: true), 'data-no-turbolink' => true
- else
  = link_to '支付宝付款', pay_recharge_path(resource, alipay: true), class: 'button', 'data-no-turbolink' => true
  = link_to '微信支付', pay_recharge_path(resource, scan_wepay: true)
  = link_to '银联付款', pay_recharge_path(resource, unionpay: true), 'data-no-turbolink' => true

其它经验

  • iOS App 我们用 WKWebView 套的壳,WKWebView 比 UIWebView 性能更好些,但限制也更多些,具体可以 Google。
  • Android App 我们用默认的 WebView,目前没发现更好的替代品。
  • 支付渠道之前我们是自己封装的,现在发现 Ping++ 也不错,大家可以试试。

重点来了!!!

简单心理是什么?

  • 最大的华语心理咨询平台
  • 最严格的咨询师入驻审核
  • 立志于提供最专业的心理服务

内心世界那么大,想不想来看看?

我们需要:

  • Ruby 工程师 月薪 15k 起

我们提供:

  • 最人性化的工作环境(老板及大部分员工都有心理学专业背景,程序员鼓励师弱爆了 😏
  • 非北京地区可远程工作(本部位于北京中关村)

欢迎勾搭 [email protected]

休息下,看看养眼的照片吧(非 PS)

女王大人(曾用名:煤球)及她的孩子们 猫

各种帅哥美女云集的活动 帅哥美女

了解更多我们公司的详情可以移步这里: http://www.jiandanxinli.com/pages/37

快到我们的碗里来~

非常有用的介绍,有机会一定看看

原来是硬广

人才哦,看到页末才发觉,精彩在最后。

这样的广告看得舒服

欢迎这样的广告。

早就喜欢上简单心理了,果然背后有一个高效率的好团队 哈哈

么么哒~

如果大家对简单心理感兴趣,我们欢迎更多小伙伴呢~ https://ruby-china.org/topics/27233

赞呀!

不仅仅是广告

总共花了多少时间呢

14 Floor has deleted

仔细对比了一下网页端和 app, 完全就是浏览器套壳吗?太厉害了! 话说这方面有什么推荐的教程?我也想给自己的网站套个 app 哈哈哈

不过,怎么给这样的 app 加“分享到微信”的功能呢?

:plus1: 不错,和年初看到这个项目的时候对比变化非常大。真棒!

#3 楼 @oth 有干货的硬广 😄

#4 楼 @douxiance 最后才是重点 😏

#5 楼 @peter 谢谢,萌猫和美女总会有一个被喜欢的 😆

#6 楼 @lgn21st 以后会越来越多哒 😛

#7 楼 @billzbc 谢谢关注,想加入吗? ☺

#11 楼 @cys 还有萌宠和帅哥美女 :metal:

#13 楼 @hw676018683 因为这是公司的主要产品,并不是一开始就设计成这样的,所有没有一个固定的时间。产品已经上线一年多了,之前我们也采用过 PhoneGap 等方法,不过都没达到我们的预期。

现在这个方案是 5 月份开始做的,安卓和苹果的应用开发到上线用了一个月。

#15 楼 @cqcn1991 这是原生应用,所有第三方 SDK 都可以按原生应用的方式接入。这也是废弃 PhoneGap 的原因,因为要接入 PhoneGap,你还得把 SDK 封装成 PhoneGap plugin。

#16 楼 @liwei78 我没记错的话当初跟你聊的时候,有说过准备采用这个方案 😄

和楼主 交流一下,感觉还是蛮有收获的,其中有一个比较大的收获是:用 Swift 的 WKWebView 代替原来的 UIWebView 来提升 webview 加载速度 和 减少内存的使用。

最后还是给楼主 点个👍

都有心理学背景!细思恐极!不约!

#25 楼 @zfben 什么意思?就是说,尽管这个 App 看起来和网站一模一样,但实际上是完全重写的?

中间的妹子不错

#30 楼 @tq0fqeu 中间的妹子是创始人 CEO 哟。。。

#19 楼 @zfben 错,我喜欢上面的分享,下面的都是广告。

#29 楼 @cqcn1991 App 就是个浏览器的壳,但是分享之类的功能,不属于 Web 的范畴了,需要另外开发。

为纠结开发模式的筒子们提供了强力的参考啊~ 硬货+企业文化~~必须顶。

@hbin 真真的 -:

一个大神等于一群虾兵蟹将!

手机版体验一下,在 iPhone 6p 上,有一些布局有点小问题,返回可能点击反应不太灵。总体感觉与 native 的应用有较大差距。

#38 楼 @pingfengsoft basecamp 把导航做成了 native,我们的导航一直在改版,所以目前不能固化成 native

WKWebView 不支持 iOS 7 吧,还是有不少用户的

主要部分加壳 webview,定制部分,如分享,消息推送通过第三方使用 native 方式实现,比如消息推送,把第三方 SDK 加进去,利用 navtive 消息机制唤起 app,并到达某个具体的消息页,是否可以这么理解?

#40 楼 @swordray 我们的 App 只支持 iOS 8 及更新版本,因为是用 Swift 写的

#42 楼 @zfben Swift 可以支持 iOS 7

#43 楼 @zfben 当时有个项目需要快速开发,本来也想这么干的,关键点是不是,navtive 需要建 bridge 到 web 通过 js 进行交互,如果有机会未来可以尝试。

看过你们的 APP,UI 不是很理想,几个简单的方面吧

  • 字号太小;

  • 边距控制不理想,比如底部工具条,留边边距吧;

  • 阅读列表 图,标题,时间,留白比例不太合适;

  • 启动图片精度应该不够;

  • 打开 APP,Home 键,再点击 APP ICON,就闪退了,iphone 6 plus;

PS:要做一个可用的 APP 还是挺花时间的,太多的细节了;

#44 楼 @swordray 谢谢提醒,才发现 Swift 原来最低支持 iOS6

#45 楼 @wikimo 所以我们一直在招设计师和前端。新版本对闪退做了一些优化,不过还在待审核,请耐心等待 ☺

下载 ios 版的看了下,觉得对于套了成壳的 app 毕竟还是跟原生有差别。 其实做 hybrid app,我觉得可以尝试下 http://www.dcloud.io/runtime.html,不仅在 ios 上表现很好,android 也还不错。

You need to Sign in before reply, if you don't have an account, please Sign up first.