Intro

CodePush 是一個雲端服務,能夠讓 Cordova 和 React Native 的開發者將手機應用的更新,跳過提交審查,直接部署到用戶的設備上。 它擔任類似中間倉庫的角色,開發者可以把更新(JS,HTML,CSS和圖片)發佈到這個倉庫上,透過程式碼的整合,Apps 就能夠查詢到更新並且下載。

Setup CodePush Service

首先我們先從 CodePush 服務的準備開始~~

Install CodePush Management CLI

首先我們需要安裝 CodePush CLI

$ npm install -g code-push-cli

安裝完後察看版本確認安裝成功

$ code-push -v

Register & Login CodePush

$ code-push register

執行後會開啟網頁讓你進行註冊,並在 terminal 要求填入 access key

可以直接透過網頁以微軟或Github帳號做第三方登入進行授權

註冊登入後頁面會給你 access key

此時複製回到 terminal 貼上

  • 登入:$ code-push login
  • 登出:$ code-push loout

Add new App

$ code-push app add <appName>

新增完後透過 ls 指令確認新增成功

新增的 App 將會有兩個預設的環境

  • Staging:通常用來當作開發中的部署環境
  • Production:上線的部署環境

每個部署環境可以當成是 git 當中不同的 branch 概念

也能夠從 history 進行版本控制,做一些 rollback 的動作

Get Deployment Key Of App

$ code-push deployment ls <appName> -k

就能看見該 App 所有部署環境的 deplyment key

React-Native-Code-Push 整合

文件寫得相當詳細,Step by step 照著文件作就可以

這邊簡單說明流程

由於不同的 React Native 版本所需要做的配置略有不同

這邊以 React Native v0.41.2 為例

  1. 安裝 react-native-code-push :

    $ npm install --save [email protected] 點一下這邊 確認 RN 版本和套件支援的版本相依性

  2. 安裝完後,接下來需要 link

    由於 React Native 版本在 0.27 之後,已經將 rnpm link 合併到 React Native CLI

    直接使用

    $ react-native link react-native-code-push

    0.27 以下的版本則可以透過 $ rnpm link 設置,詳細可以參考 Setup

  3. 安裝完後還需要做兩個整合的動作 (這邊的設置方式對應不同的 RN 版本也有差異)

    • 設定 deployment key 到專案中

      • Android :

        編輯 android/app/src/main/java/com/<ProjectName>/MainApplication.java

        1
        2
        3
        4
        5
        6
        7
        @Override
        protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
        new MainReactPackage(),
        new CodePush("Deployment_Key", getApplicationContext(), BuildConfig.DEBUG)
        );
        }

        填入 app 的 deployment key

      • iOS :

        ios/<Project_Name>/info.plist

        可以看見 CodePushDeploymentKey 欄位,在 value 欄填入 deployment key 即可

  4. 最後是整合 JS 的部分

    使用 HOC (Higher Order Component) 的方式就能快速的整合到你的 App 中了

    程式碼如下

    1
    2
    3
    4
    5
    6
    import codePush from "react-native-code-push";
    class MyApp extends Component {
    }
    MyApp = codePush(MyApp);

進行更新

release-react 是專門更新 React Native 專案的指令

會自動將目前檔案產生 bundle 並上傳更新版本到 CodePush 的雲端上

$ code-push release-react <appName> <platform> -d <deploymentName>

如果沒有給 -d 的 deploymentName 參數的話,預設將會是 Staging

Read More

留言與分享

上一篇 中,我們應該已經設定好了自定義域名,接下來就是幫我們的自定義域名加上漂亮安全的 https 綠色鎖頭啦。

Add Free SSL

說到 Free SSL 相信很多人第一個想到的就是開源的 Let's Encrypt 吧,不過很遺憾在爬文時發現,Github 似乎並不支援 Let's Encrypt ,因此只好找其他的免費 SSL 憑證了,這篇要說明如何使用 CloudFlare 幫 Github Pages 掛上的免費 SSL

  1. 註冊 CloudFlare 帳號 如果你和我一樣只是要用免費版的 SSL,註冊完不必填信用卡資訊,直接到信箱收信

  2. 由此登入 點選 Add website 新增你的域名,ex: dmoon.space 確認後會開始掃描你的域名將地區檔設定掃出來,自動設定到 CloudFlare 的 DNS 上 接著他會提供幾個他設定好的 DNS 位址給你,請你到域名提供商的館理頁面,設定為他提供給你的 DNS

  3. 設定 CloudFlare 提供的 DNS 例如我是在 gandi 上買的域名,回到 gandi 域名管理頁的右下角會看到 域名伺服器,按下 修改伺服器 設定為 CloudFlare 提供的 DNS

  4. 等待... 等待... 再等待...

    更改 DNS 需要等滿久的時間才會生效,我等了應該有四五個小時,在他生效之前我們可以繼續下一步處理一些額外的設定

  5. 請先到 CloudFlare website 管理頁面,將 Crypto / SSL 設定為 Flexible 如圖:

    flexible_config.png

    好奇 Flexible 意思的請點這裡 Read More...

  6. 到這邊差不多就完成囉 接下來是對網站做一些額外設定 像是在 中加上

    1
    2
    3
    4
    5
    <script type="text/javascript">
    var host = "yoursite.com";
    if ((host == window.location.host) && (window.location.protocol != "https:"))
    window.location.protocol = "https";
    </script>

    讓 http 的連線自動導向到 https

  7. 告訴搜尋引擎偏好網址 將下面加入你的 Hexo theme header template 中

    1
    <link rel="canonical" href="<%= url %>" />

Reference

https://sheharyar.me/blog/free-ssl-for-github-pages-with-custom-domains/

留言與分享

最近看到好多人的 Github Pages 都有了自己的域名和 https,剛好在 Gandi 上看到 space 的 domain 好便宜,心血來潮於是就買了一個來玩,之前其實沒有碰過 domain 相關的設定,原先想說可能會有點麻煩,沒想到比預期還要容易許多,簡單做個筆記記錄一下,整個過程需要對 Github Pages, Gandi, CloudFlare (SSL) 做一些設定。

我們先從 custom domain 開始吧

Set Custom Domain

  1. 購買域名

    我是在 gandi 購買的,大家可以到各域名商的網站上搜尋喜歡的域名進行購買,租期到了要記得續訂,才不會發生慘劇。

  2. 設定 區域檔

    在 gandi 購買完後,進入 domain 的 管理頁面找到 編輯區域檔 的連結,進入區域檔的編輯頁面,( gandi 無法更改現正套用的設定檔,所以需要先新增一個來編輯,編輯好再選擇套用) ,總之最後設定的結果應該要長這樣

    gandi-zone-configure.png

    192.30.252.153 , 192.30.252.154 是 Github 的位址 第三個 CNAME 的設定,name 的地方可以填你想要的子網域(subDomain),value 則是填寫你的 github.io 網址(最後記得加上一個 . ex: kyoyadmoon.github.io.

    需要畫面截圖參考,請點這裡

    記得使用新編輯的設定!

    記得使用新編輯的設定!

    記得使用新編輯的設定!

  3. 等待 & 設定 Github Page CNAME 

    等待設定更新需要一些時間,多久不一定,可能幾分鐘也可能幾小時

    如果你在瀏覽器輸入你設定的子域名能夠看到 Github 的頁面(這時應該是 Github 404 頁面)表示更新生效了

    在等待的時間我們可以先來設定 Github CNAME

    能夠讓輸入原本 Github Pages url 時,自動導向到你的域名底下

    demo:

    試著開啟我的 Github Page 網址:https://kyoyadmoon.github.io/blog/

    會看到自動導向到 https://blog.dmoon.space 底下

    Github Page CNAME

    設定方法是在跟目錄底下新增一個 CNAME 檔案

    1
    blog.dmoon.space

    裡面填寫你設定的域名就可以了

    和我一樣是 Hexo 的使用者請看這裡!

    如果直接透過 git 添加到 github 上的話,下次 hexo generate, hexo deploy 時就會被覆蓋掉

    請把 CNAME 檔案放到 /source/ 底下

    hexo g 就會產生對應的檔案囉

  4. Hexo 設定

    _config.yml 中將 url 設定為新的域名

    設定好之後記得用 hexo g && hexo d 更新 blog

想要加上免費的 SSL 簽證,完成 HTTPS 綠色鎖頭請見 Hexo Github Pages 免費 SSL 設定

Read More

Reference

留言與分享

我是 2015 年初購買的 MacBook Pro (Retina, 13-inch, Mid 2014),使用上體驗真的很棒,覺得非常值得,但用了大約半年後,從中間開始出現輕微的鍍膜剝落情形,立馬上網 Google,發現全球災情不少,但即使是保固內,仍有多例在官方評估後認為是人為損害,無法免費維修。引起網友連署希望官方處理,當時看完也是心涼了一截,花了許多錢才買的電腦沒想到半年就出了狀況。之後一邊 follow 相關消息,剝落狀況也漸漸擴散,明顯可以看出鍵盤按鍵的輪廓痕跡,合理推測是螢幕闔上時,和鍵盤接觸導致的鍍膜剝落,心想這應該是設計上的問題,如果真的不處理,對於蘋果實在相當失望。

最後在 2015 年底的時候,在 MACUKNOW 上面看到官方將會針對鍍膜剝落的 Retina MacBook 提供免費維修服務,心裡的大石頭才放下了些,雖然去年十一月就看到了消息,不過因為實習的工作需要,也沒辦法將筆電送修一個禮拜之久,於是一直拖到兩個禮拜前才送修。

送修過程

由於台灣並沒有 Apple 直營的維修中心,只有授權維修中心,於是爬了一些網路上的文章,覺得 STUDIO A 相對好評較多,維修門市本就較少,也不是所有維修門市業務內容都包含 MacBook,最後選擇到大安門市送修(有提供線上預約),只需要帶著 MacBook 過去就可以了

幾點注意事項:

  1. 建議先做好備份 (雖然理論上只會更換螢幕,還是以防萬一)
  2. 或許你也有貼貼紙的習慣,如果順利更換營幕的話,貼紙是拿不回來的
  3. 不需要攜帶配件,填寫維修單後,他們會將電腦代送給 Apple 評估是否能免費維修。

果然一週後就接到電話通知,能夠到維修門市領取啦。

留言與分享

React Native

在上一篇 React Native 初心者攻略 中有說明如何在實體 iPhone 上開發

透過 AppDelegate.m 這個檔案我們可以將 localhost 手動更改成電腦 ip 來達到實機測試的目的

但是這樣的開發方式有幾個缺點

  1. 需要經常手動去做更改,尤其當你是使用筆電,甚至是和其他人共同開發的狀況,就會常常在 merge 時衝突,除非團隊都使用 localhost 以 simulator 進行開發
  2. 沒辦法在實體機器上 Debug in Chrome

在開發一段時間後,實在受不了,好在找到了自動設定的方法

透過 shell script 抓取電腦的 IP 後,寫入到專案

設置方法

抓取電腦 IP

我們需要先寫出能夠抓取電腦 IP 的指令

網路上大多使用這個指令,可以先填到 terminal 執行看看,確認 IP 是否正確

ifconfig | grep inet\ | tail -1 | cut -d " " -f 2

但是因為我們專案後端 server 有使用到 docker ,使用上面 command 抓到的是錯誤的 IP

所以我需要改成這樣

ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1

OK 我們現在能夠拿到正確的 IP 了

Add Run Script

再來我們需要設定在專案執行時執行一段 shell script 去抓取 IP 寫入到專案中

照著圖中藍色 focus 的地方找到 Build Phases

addScript.png

新增一個 Run Script 後的畫面

editScript.png

接下來就是填入主角 script 了

下面的 script 會在專案的 INFOPLIST 裡新增一個 SERVER_IP 的欄位,並把 IP 寫入

1
2
3
4
5
6
INFOPLIST="${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"
echo "writing to $INFOPLIST"
PLISTCMD="Add :SERVER_IP string $(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1)"
echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" || true
PLISTCMD="Set :SERVER_IP $(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\.){3}[0-9]*' | grep -Eo '([0-9]*\.){3}[0-9]*' | grep -v '127.0.0.1' | head -1)"
echo -n "$INFOPLIST" | xargs -0 /usr/libexec/PlistBuddy -c "$PLISTCMD" || true

填好之後會像這樣

addedScript.png

AppDelegate.m 讀取 SERVER_IP

打開 AppDelegate.m

將原本

1
jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];

替換成能夠動態改變 SERVER_IP 的 code

1
2
3
4
NSString *serverIP = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"SERVER_IP"];
NSString *jsCodeUrlString = [NSString stringWithFormat:@"http://%@:8081/index.ios.bundle?platform=ios&dev=true", serverIP];
NSString *jsBundleUrlString = [jsCodeUrlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
jsCodeLocation = [NSURL URLWithString:jsBundleUrlString];
AppDelegate.png

這時候你可以測試看看 simulator 和 real device 上是不是都能正常運作,可以的話就成功囉!

Debug in Chrome on Real Device

找到 RCTWebSocketExecutor.m 的 setUp

RCTWebSocketExecutor.png

將這行

1
NSString *URLString = [NSString stringWithFormat:@"http://localhost:%zd/debugger-proxy?role=client", port];

替換成

1
2
NSString *serverIP = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"SERVER_IP"];
NSString *URLString = [NSString stringWithFormat:@"http://%@:%zd/debugger-proxy?role=client", serverIP, port];

這邊一樣是將 localhost 改成 SERVER_IP

實體裝置就能透過 wifi 在電腦的 chrome 上進行 debug 了,趕快試試看!

Reference

http://moduscreate.com/automated-ip-configuration-for-react-native-development/

留言與分享

React Native

由於 React 的火熱程度,身邊許多朋友都開始接觸 React ,我也推薦他們玩玩看 React Native ,我覺得 React 的入門門檻有些其實和 React 本身無關,像是 Webpack, Babel 等等都多少在無形中增加了入門的難度,且有許多範例可能還使用了 ES6 語法,雖然不是必要,但可能會造成初學者混淆、失去信心,使學習過程更不順利。

然而 React Native 完全就是一個超棒的東西,只要跟著官網的教學就可以很簡單的開始使用 React 撰寫跨平台的 App,不僅內建支援 ES6 ,還有 Live Reload , Hot Reloading 等強大功能, 甚至能在 Chrome 中 debug ,這些React Native 統統幫你包好了,省去了原先我們在 web 專案開發需要自行加入 webpack, babel 等等的處理過程。

環境建立

相關環境安裝的部分跟著 官網的詳細指示 (別擔心這裡有中文版) 操作就可以了,這部分就不多敘述

建立RN專案

$ npm install -g react-native-cli
$ react-native init AwesomeProject

iOS

環境準備

安裝 Xcode 即可

專案開發

有兩種方法

第一種是使用 Xcode :

開啟專案目錄下的 /ios/AwesomeProject.xcodeproj (應該會以 Xcode 開啟), 按左上角的播放圖示按鈕就會自動開啟 iPhone 模擬器和 Packager server ,並把專案 build 成 App 到模擬器中。

另一種是開啟 terminal 切換到專案目錄

$ react-native run-ios

這個指令可以不用開啟 Xcode 做和上面同樣的事情,一個指令解決,非常簡潔

接著你就可以開始編輯專案目錄下的 index.ios.js 開始開發你的專案。

Tips

在模擬器的 RN App 中你可以用快捷鍵 cmd+D 打開開發 Menu,這邊可以設定 Debug in Chrome, Live Reload, Hot Reloading 等等功能。

若需要手動刷新可以使用熱鍵 cmd+R

另外,如果你有實體 Apple 裝置的話,也能夠直接在實體裝置上測試、開發

  1. 將 Apple 裝置用USB線連接到電腦,並和電腦連接同一個 wifi

  2. 將專案用 Xcode 開啟(上面的第一種方法)

  3. 在 Xcode 左上角播放圖示的右方應該可以看到 寫著 Apple 裝置的選項,點按後選到自己的實體裝置

  4. 打開 Xcode 左邊檔案管理的導覽列 Tree View,找到 AwesomeProject/AppDelegate.m 這個檔案打開來 可以在裡面找到這段,相信看到註解大家應該都知道要怎麼做了,把 localhost 換成電腦的 ip 就可以了

    1
    2
    3
    4
    5
    6
    7
    8
    /**
    * To run on device, change `localhost` to the IP address of your computer
    * (you can get this by typing `ifconfig` into the terminal and selecting the
    * `inet` value under `en0:`) and make sure your computer and iOS device are
    * on the same Wi-Fi network.
    */
    jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
  5. 按下 Xcode 左上角的播放鍵開始 Run 囉

Android 環境準備

由於目前我主要都是在 iOS 上開發, Android 部分還沒有很了解,如果有漏掉什麼還請各位大大提醒

Android 在 OS X 上的環境準備相對 iOS 來說稍微麻煩一點,但也不難 細心按照官方指示應該就能成功囉

參考這裡

開發準備

安裝完 Android SDK 和 Genymotion 之後

先打開 Genymotion 創建一個模擬器啟動

接著開啟 terminal 切到專案目錄下

$ react-native run-android

然後就可以編輯 index.android.js 開始開發了

在模擬器中按下 menu 按鈕可以打開開發 Menu ,這邊可以設定 Debug in Chrome, Live Reload, Hot Reloading 等等功能。

如何使用別人寫好的 library, Package

我的同事 yaode 寫了一篇詳細完整的教學文章 大家可以參考看看

http://trunk-studio.com/blog/react-native-how-to-use-component/

記得有用到文章內的方法 link library 的話,是需要重新 build App 到模擬器才能正常運作的喔!(run-ios / run-android)

留言與分享

昨天在處理為 React Native 加上 聊天室的功能,首先遇到的問題就是串接 Socket ,要在 RN 上使用 socket 需要安裝 socket.io-client,安裝之後 import socket.io-client/socket.io 時,遇到了這個 error

undefined is not an object (evaluting 'navigator.userAgent.match')

找了一下解決方法 發現這個套件不能用 import ,必需用 require 另外需要 assign window.navigator.userAgent

正確設定方法如下

1
2
3
4
5
6
7
import React, { Component } from 'react-native';
window.navigator.userAgent = 'react-native';
const io = require('socket.io-client/socket.io');
const socket = io('ws://', { jsonp: false });

#Reference

http://browniefed.com/blog/2015/05/16/react-native-and-socket-dot-io/

留言與分享

ESLint

之前一直沒有嘗試過 JSHint、ESLint ,但隨著合作開發的人數越來越多,程式碼的風格和規範問題就更加明顯,加上最近看了聖經 Clean Code ,覺得寫出乾淨的程式碼真的很重要,剛好爬文發現有人推薦 Airbnb 釋出的 ESLint config 來做 js 和 React.js 規範,所以就決定來嘗試看看!

首先我要推薦 eslint-plugin-react 這個套件,這套件除了規範 React 的一些寫法,重要的是他還有寫 rules 的文件,告訴你為什麼建議這樣寫,只要把 eslint 上出現的錯誤訊息,拿去 google 就會找到 github 上用 markdown 寫的相關說明,跟著寫就有種 Level Up 的感覺,實在受益匪淺!

#Setup

安裝方法很簡單

先使用 npm 安裝 eslint 、 eslint-plugin-react、eslint-config-airbnb

npm install --save-dev eslint eslint-plugin-react eslint-config-airbnb

安裝後可以利用指令 init .eslintrc.js

eslint —init

透過 .eslintrc.js 這個檔案可以編輯 eslint 的規則

加入 extends airbnb 和 react plugin 就可以了

因為我有使用 es6 語法 所以需要多一個 babel 當 parser

1
2
3
4
5
6
7
8
9
10
11
/* .eslintrc.js */
module.exports = {
"extends": "airbnb",
"plugins": [
"react"
],
"parser": "babel-eslint",
"rules": {
"strict": 0
},
};

留言與分享

Koa.js

之前在設定 Koa 的 cache 時,有點小卡關,所以記錄一下

我使用的 Koa 版本是 2.0.0

搭配處理 cache 的套件 是 koa-static-cache

官方 readme 上面的範例用法長這樣

1
2
3
app.use(staticCache(path.join(__dirname, 'public'), {
maxAge: 365 * 24 * 60 * 60
}))

因為使用 Koa 2.0 的關係,需要 koa-convert 套件 convert 還沒更新支援 Koa 2.0 的套件,才能使用

所以我改成這樣

1
2
3
app.use(convert(staticCache(path.join(__dirname, 'public'), {
maxAge: 365 * 24 * 60 * 60
})))

不過卻沒成功

後來看了別人的 Sample 才知道 StaticCache 後,還需要 mount 到 route 上

1
app.use(convert(mount('/public/assets/js', staticCache(path.join(__dirname, '../public/assets/js/'), {maxAge: 30 * 24 * 60 * 60}))));

最後改成這樣終於成功啦!

留言與分享

GMT & UTC

首先來說 GMT 和 UTC 是什麼,有什麼差別

GMT:格林威治標準時間

UTC:世界協調時間

他們都是世界標準時間,而 UTC 的算法更為嚴謹,所以比 GMT 更為精準,不過兩者的差異是極小的,所以基本上時間是可以看作相同的

Linux Etc/GMT 時區為何正負顛倒

當你使用 Linux 設定時區時 ,若是選用 Etc 底下的 GMT 時區,可能會發現設定的結果與你預想的不同,當你想設定台北的時區 (GMT+8) ,但設定完後,系統時間卻是 -8 的時區,和台北時間相差 16 小時,原因是因為 Etc 底下的 GMT 時區是以 格林威治 以西為正,以東為負,剛好與我們現實生活的認知相反

而原因只是因為當初 Unix 多為西方人使用,便以西為正

因此在設定的時候需要選擇正負相反的選項

Reference

http://lemonlatte.logdown.com/tags/tzdata

留言與分享

DMoon

熱愛科技的資工系學生,喜歡學習新的技術

目前主要開發 Web APP

較熟悉的技術是 Node.JS / React.JS


學生 / 創科資訊實習生


Taichung, Taiwan