1.背景
移動互聯(lián)網(wǎng)發(fā)展到今天,由于H5的跨平臺、高效率、低成本等優(yōu)勢,我們的前端開發(fā)工作內(nèi)容已不僅僅局限于瀏覽器端的網(wǎng)頁,現(xiàn)在很多應(yīng)用都已經(jīng)引入了新的開發(fā)模式:Hybrid APP。
Hybrid APP底層依賴于Native提供的容器(UIWebview),上層使用HTML、CSS和JavaScript來開發(fā),這樣的方式使得應(yīng)用更新迭代變得更加敏捷和高效,所以Hybrid APP應(yīng)用越來越多。但是隨之而來的會有很多新問題,比如今天我們要談到的實際開發(fā)中前端如何模擬客戶端環(huán)境實時調(diào)試。
傳統(tǒng)的前端開發(fā),在PC端我們可以用瀏覽器直接打開html頁面,實時查看和調(diào)試頁面,移動端可以借助類似BrowserSync這種實時同步工具來調(diào)試,但是在Native下,很多時候我們需要依賴用戶的信息或者依賴客戶端的一些行為,只能先提測或者上線,讓客戶端同學(xué)給配一個測試或線上入口url,每次更新了代碼,都要push代碼,然后在客戶端內(nèi)查看效果,這還只是應(yīng)對新需求未上線的功能,一旦項目上線有bug需要修復(fù),我們沒有客戶端的真實環(huán)境,比如測試環(huán)境沒有正式環(huán)境的某些數(shù)據(jù),很難將問題復(fù)現(xiàn)出來,也不可能拿線上代碼直接去push調(diào)試,所以這種方案顯然不合理。那么有什么辦法能讓我們修改完本地代碼后,直接重載客戶端的Webview,就能實時看到Native中最新效果了呢,下面介紹一種開發(fā)模式,滿足我們的Hybrid H5開發(fā)需求。先來看看一個實際案例:
2.案例描述
前些天測試同學(xué)給我提了個bug單,大概是這樣的:我們的書城客戶端內(nèi)有一個專題,內(nèi)容是一些書籍列表,每個書籍都有一個『閱讀』按鈕,bug現(xiàn)象是“打開的書籍與專題中實際點擊的不一致,打開的是該專題下最后一本書。”。看描述猜測原因應(yīng)該是:點擊閱讀按鈕時候調(diào)用的 readbook() 方法,需要傳入所選書籍信息作為參數(shù),傳參邏輯出現(xiàn)了問題。
因為這個專題模板之前不是我寫的,專題模板又兼容了多類專題,代碼量龐大,所以熟悉了下代碼框架后先基本確認(rèn)了問題點,果然是這里的readbook() 方法的參數(shù)在列表循環(huán)數(shù)據(jù)的時候被覆蓋了,這里需要重新兼容一個邏輯處理,修復(fù)完畢。但是改別人的代碼最擔(dān)心的就是牽一動百,而且這個專題只有線上正式環(huán)境才有,測試環(huán)境沒有,也不想再去麻煩運(yùn)營同學(xué)給測試環(huán)境配一堆數(shù)據(jù),所以問題來了,怎么才能在本地客戶端環(huán)境實時調(diào)試H5而不把風(fēng)險留給正式環(huán)境來測呢?先梳理下思路。
3.思路梳理
我們需要搞清楚兩個問題:
1.如何本地調(diào)取線上環(huán)境接口數(shù)據(jù),沒數(shù)據(jù)我們無法測試該專題;
2.如何將本地代碼實時同步到客戶端內(nèi)訪問。
先看第一個問題,我們的js網(wǎng)絡(luò)協(xié)議層的方案大概是這樣的,先判斷當(dāng)前url域名是不是線上域,是的話就調(diào)正式環(huán)境后端服務(wù)接口,否則就掉測試環(huán)境后端接口,網(wǎng)絡(luò)協(xié)議層一般是不動的,我不能為了測試去修改網(wǎng)絡(luò)層規(guī)則再提測,這也是不合理的,所以解決這個問題的第一步,就是模擬正式域。這里我們的方案思路是使用nginx代理服務(wù)器配合修改hosts文件來實現(xiàn),將正式域名 iyuedu.qq.com 在開發(fā)環(huán)境中直接指向本地代碼,有了這個基礎(chǔ),第二個問題自然想到通過給手機(jī)掛代理來實現(xiàn)。
4.安裝nginx服務(wù)器
首先安裝nginx服務(wù)器,以下演示以Mac為例,Windows下nginx安裝見此。
1.Homebrew安裝
Mac下nginx要通過Homebrew來安裝(簡稱brew),brew是Mac OSX上的軟件包管理工具,能在Mac中方便的安裝軟件或者卸載軟件。
Homebrew的安裝非常簡單,打開終端復(fù)制、粘貼以下命令,回車:
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew安裝完畢后,可以在終端輸入命令「brew -v」檢查以下是否安裝成功(若失敗,多試幾次):
返回了Homebrew 1.2.1版本號,說明brew已經(jīng)安裝成功。
2.nginx安裝
接下來繼續(xù)安裝nginx,執(zhí)行命令:
brew search nginx
brew install nginx
可能由于網(wǎng)絡(luò)因素,安裝的時候花費了很長時間,中間失敗了兩次,所以這里如果安裝不順暢,請多嘗試幾次即可。
同樣安裝完畢后我們可以通過命令「nginx -v」查看nginx是否安裝成功:
返回 nginx/1.12.0 版本,搞定。
5.修改ngnix.conf配置
nginx已經(jīng)安裝完畢,但是我們還要通過對nginx的一些配置,讓它使我們的線上域名“ iyuedu.qq.com ”在本機(jī)中指向本地的代碼目錄。
打開Finder,前往文件夾 “/usr/local/etc/nginx/” ,然后找到 nginx.conf 文件,打開并進(jìn)行編輯:
找到 http 下的 server,進(jìn)行如下配置修改:
server {
listen 80;
server_name iyuedu.qq.com;
set $path '/Users/luping/Desktop/work/git_code/baipai/oppo-webapp-html/WebContent/6_0/';
location / {
root $path;
index index.html index.htm;
autoindex on;
}
}
這里我們使用 80 端口,server_name很好理解,就是我們主機(jī)的名稱,我們使用線上域名“iyuedu.qq.com”,然后設(shè)置一個變量$path來保存本地代碼路徑,在location中賦值給root。
保存,關(guān)閉,其他的地方保持原配置暫不用修改。
注意,這里會有兩個坑,后面運(yùn)行的時候再分析解決。
6.修改hosts文件
hosts文件是一個用于儲存計算機(jī)網(wǎng)絡(luò)中各節(jié)點信息的計算機(jī)文件,我們可以配置ip地址和其對應(yīng)主機(jī)名。
打開Finder,前往文件夾 “/private/etc/hosts” ,找到hosts文件,先復(fù)制一份到桌面,然后打開,我們將默認(rèn)的 “127.0.0.1 localhost” 先注釋,再添加一條:
# 127.0.0.1 localhost
127.0.0.1 iyuedu.qq.com
保存后,在粘貼回 “/private/etc/hosts”目錄下,這里需要提供下管理員密碼,繼續(xù)即可。至此我們的hosts文件也修改完畢,將本地的ip對應(yīng)到了我們的想要的正式域名“iyuedu.qq.com”。
7.啟動&解決問題
1.啟動
終于等到這一刻,是時候看一下修煉成果了,我們需要啟動nginx服務(wù),這里先普及下nginx常用的幾個命令:
sudo nginx #打開 nginx
nginx -s reload|reopen|stop|quit #重新加載配置|重啟|停止|退出 nginx
nginx -t #測試配置是否有語法錯誤
nginx [-?hvVtq] [-s signal] [-c filename] [-p prefix] [-g directives]
-?,-h : 打開幫助信息
-v : 顯示版本信息并退出
-V : 顯示版本和配置選項信息,然后退出
-t : 檢測配置文件是否有語法錯誤,然后退出
-q : 在檢測配置文件期間屏蔽非錯誤信息
-s signal : 給一個 nginx 主進(jìn)程發(fā)送信號:stop(停止), quit(退出), reopen(重啟), reload(重新加載配置文件)
-p prefix : 設(shè)置前綴路徑(默認(rèn)是:/usr/local/Cellar/nginx/1.2.6/)
-c filename : 設(shè)置配置文件(默認(rèn)是:/usr/local/etc/nginx/nginx.conf)
-g directives : 設(shè)置配置文件外的全局指令
好了,首先我們啟動nginx:
sudo nginx
按照配置,我們把本地的localhost修改為了“iyuedu.qq.com”,然后直接指向了代碼目錄,所以理論上我們打開瀏覽器直接訪問 “http://iyuedu.qq.com/topicV2.html” 就可以訪問到這個專題文件topicV2.html了,試一試:
發(fā)現(xiàn)nginx給我們報了個錯,提示 “403 Forbidden”,目測是權(quán)限問題,nginx不允許查看。看來我們還要再修改一下nginx.conf配置文件,在nginx.conf文件的最頂部加一句
user root owner;
保存,然后在終端重啟nginx:
sudo nginx -s reload
在瀏覽器中再刷新一下:
看樣子好像成了,我們幾乎達(dá)到了目的,本地訪問域名“iyuedu.qq.com”但實際訪問的是本地的代碼,而且顯然已經(jīng)成功的取到了后端線上接口數(shù)據(jù),經(jīng)測試,修改了一下本地代碼,瀏覽器中一刷新,頁面會立刻看到更新改動,這不正是我們想要的嗎,但是,好像還差那么一點點,對比了下這個專題真正的線上url,是這樣的:
http://iyuedu.qq.com/act/6_0/topicV2.html
而我們目前模擬出來的是:
http://iyuedu.qq.com/topicV2.html
對比發(fā)現(xiàn),我們模擬的url缺少了一部分路徑 “/act/6_0”,這樣的話顯然不能進(jìn)行下面的代理客戶端中頁面url的工作了,所以我們必須要模擬得一模一樣!
好吧,我們繼續(xù)填坑。
2.解決,location中root和alias
上面我們只是用nginx和hosts來啟動了服務(wù)和修改了本地ip對應(yīng)的主機(jī)名稱為我們的正式域名,那么繼續(xù)給這個域名配一個虛擬的路徑,誰來做呢?當(dāng)然還是nginx, hosts文件能力有限,只能修改一下主機(jī)名稱,真正挑大梁的還是nginx。
原來nginx.conf中的location指定文件路徑有兩種方式:root和alias。
root與alias主要區(qū)別在于nginx如何解釋location后面的uri,這會使兩者分別以不同的方式將請求映射到服務(wù)器文件上。
[root]
語法:root path
默認(rèn)值:root html
配置段:http、server、location、if
[alias]
語法:alias path
配置段:location
root實例:
location ^~ /path/ {
root /www/page/html/;
}
如果一個請求的URI是 /path/a.html 時,web服務(wù)器將會返回服務(wù)器上的 /www/page/html/path/a.html 的文件。
alias實例:
location ^~ /path/ {
alias /www/page/html/;
}
如果一個請求的URI是 /path/a.html 時,web服務(wù)器將會返回服務(wù)器上的/www/page/html/a.html的文件。注意這里是 /www/page/html ,因為alias會把location后面配置的路徑“/path”丟棄掉,把當(dāng)前匹配到的目錄指向到指定的目錄。
知道了這一點,我們要做的就是使用alias修改一下nginx.conf,我們?nèi)鄙俚穆窂绞恰?strong>/act/6_0/”,所以修改如下:
server {
listen 80;
server_name iyuedu.qq.com;
set $path '/Users/luping/Desktop/work/git_code/baipai/oppo-webapp-html/WebContent/6_0/';
location ^~ /oppo/6_0/ { // *修改下location*
alias $path; // *使用 alias *
index index.html index.htm;
autoindex on;
}
}
保存nginx.conf文件,然后再次重啟nginx服務(wù):
sudo nginx -s reload
再次回到瀏覽器,我們輸入線上正式的url:
http://iyuedu.qq.com/act/6_0/topicV2.html?tid=327950&tf=1
刷新,頁面正常顯示:
但是,這個頁面訪問的代碼到底是不是我們本地的代碼呢,試一下便知,我們修改下“閱讀”按鈕的文案為“test”,保存看看是否及時生效:
沒毛病,成了,現(xiàn)在我們已經(jīng)完全在本地模擬了線上正式域頁面的url
,也成功取到了線上接口數(shù)據(jù),接下來就是在客戶端內(nèi)實時預(yù)覽這個頁面了。
8.客戶端實時預(yù)覽H5
我們已經(jīng)在本地啟了nginx服務(wù),修改了主機(jī)名為線上域名,所以接下來我們只需要讓手機(jī)和Mac處于同一個局域網(wǎng)內(nèi),并且給手機(jī)掛上代理,就可以在線上包客戶端內(nèi)訪問到我們的本地代碼頁面了,有了客戶端環(huán)境,我們就可以更方便地進(jìn)行調(diào)試了,這正是我們想要的。
給手機(jī)掛代理,我們需要在電腦上啟動一個常用的抓包軟件,Mac上我用的是 Charles,Windows下一般是Fiddler,啟動后一般默認(rèn)端口是8888,當(dāng)然也可以自己修改,這里我們就不修改直接使用默認(rèn)的端口號8888。
然后再找一下電腦當(dāng)前的ip,Mac-設(shè)置-網(wǎng)絡(luò) 就可以看到我的是192.168.1.112。
注意,有的公司的內(nèi)部局域網(wǎng)考慮安全因素設(shè)置了比如AP隔離等,導(dǎo)致連接到同一局域網(wǎng)內(nèi)的設(shè)備不能互相通信,當(dāng)然也不能進(jìn)行抓包等操作,這種情況下需要我們使用電腦開啟網(wǎng)絡(luò)熱點來讓移動設(shè)備連接,關(guān)于Windows和Mac開啟熱點的方式:
Windows用戶看這里
Mac用戶看這里
拿出我們的手機(jī),連接到與當(dāng)前電腦同一個wifi局域網(wǎng),對該wifi網(wǎng)絡(luò)進(jìn)行高級設(shè)置-代理,主機(jī)名輸入我們的電腦IP,端口輸入8888,然后確定保存,這時我們的手機(jī)就已經(jīng)掛上代理了。
然后打開app客戶端,找到這個專題,點擊進(jìn)去,發(fā)現(xiàn)這個頁面的“閱讀”按鈕的文案已經(jīng)是“test”了,說明我們的客戶端由于手機(jī)掛上了我們的本地網(wǎng)絡(luò)代理,url自動指向了本地代碼目錄。這樣,我們的終極目標(biāo)就達(dá)到了,現(xiàn)在客戶端環(huán)境下,我們已經(jīng)可以隨時調(diào)試本地的H5代碼了。
9.小結(jié)
這只是一個開發(fā)模式上的優(yōu)化方案,雖然略復(fù)雜麻煩一些,但是也大大提高了開發(fā)的效率和可靠性,也切實為我們解決了一些棘手的問題。由于本人經(jīng)驗和能力有限,文中提到的一些地方如有描述不準(zhǔn)確或者錯誤的地方,歡迎大家指正,也相信還有更加便捷的方法來實現(xiàn)這個需求,先這樣吧,88。 [愉快]