Ionic Framework 跨平台專案開發心得(下)
Ionic Framework 跨平台專案開發心得
文章主旨
本文介紹跨平台開發框架 Ionic,並分享實際專案中的應用方式、遇到的困難與開發心得。 最後也會聊聊 AI 模型變強之後,開發上帶來了哪些轉變。
全文分為上、下兩篇:
- 上篇:一、Ionic 是什麼/二、專案上的應用/三、面臨的困難
- 下篇:四、實際上遇到的問題/五、AI 模型帶來的轉變/六、心得結論
下篇
四、實際上遇到的問題
以下是專案中真實發生過的幾個問題。
4.1 突然加入的 PC 大版
背景:專案一開始是以手機 App 為主規劃的,沒有考慮大螢幕的版面需求。所有頁面外層都必須包 Ionic 的元件(ion-page、ion-header、ion-content、底部 Tab),而這些元件本身就是為手機的單欄、全螢幕操作設計的。
問題:
- RWD 受限:Ionic 元件的結構與樣式不好改(見 3.2),在手機版的骨架上,只能做到「把畫面拉寬」,很難變成真正適合桌機的版面。
- 需求超出原框架:業主後來對大版畫面提出了和手機版不同的需求,例如左側選單、雙欄排版、燈箱旁常駐的資訊欄、拖曳上傳與裁切等。這些不是調整斷點就能做到的,原有架構無法直接擴充。
一開始曾嘗試直接在現有頁面上套用 RWD,但改動範圍太大、影響手機版的穩定。
做法:最後只能全專案大改,甚至動到共用元件。所有 PC 畫面重新刻一份,並透過「路由+裝置判斷」做到類似 AWD(Adaptive Web Design,依裝置載入不同版面) 的效果,而不是單純的 RWD(同一份版面隨寬度伸縮):
- 裝置層:先判斷是 App 還是網頁,決定載入手機版還是桌機版畫面。
- 螢幕層:同一版內部,再以 1024px 為斷點處理寬度變化(例如桌機縮小視窗、平板)。
- 版面元件分離:桌機版的版面另外寫成獨立元件(如
*-web-layout.vue),並提供AppOnly/WebOnly元件,讓同一頁可以分別放兩邊專屬的內容。 - 版型切換:桌機版改用左側選單取代底部 Tab,由路由設定的版型搭配裝置判斷決定外框。
規模:這個分支累計異動約 166 個檔案、新增約 2.7 萬行、刪除約 9,500 行,其中有 23 個是共用元件。
心得:如果專案未來有任何「可能要做桌機版」的機會,最好在一開始就決定版面策略。Ionic 很擅長手機,但要在手機的骨架上長出桌機版,代價非常高。
4.2 權限:裝了套件也不等於能用
現象:要使用相機、相簿、通知這類手機功能,光是安裝社群套件、在程式裡呼叫還不夠。沒有另外宣告權限的話,輕則功能沒反應,重則 App 直接閃退。
原因:手機系統要求 App 必須事先在原生設定檔中宣告會用到哪些權限,而這部分社群套件不會幫你做,只能在套件文件裡找到說明,自己手動加。更麻煩的是,iOS 和 Android 的規範完全不同:
| iOS | Android | |
|---|---|---|
| 宣告位置 | Info.plist |
AndroidManifest.xml |
| 宣告方式 | 每項權限都要附上使用說明文字,例如 NSCameraUsageDescription |
列出權限名稱,例如 android.permission.CAMERA |
| 使用者看到的 | 系統跳出詢問視窗,顯示我們寫的說明文字 | 系統跳出詢問視窗,內容由系統決定 |
同一個「開相機」的功能,兩個平台要各自設定一次,寫法也不一樣。使用者拒絕授權之後怎麼處理(例如引導他到系統設定頁重新開啟),也要自己另外寫。
權限與上架審核息息相關:權限不只是「功能能不能動」,也是 App Store 和 Google Play 審核的重點。
- iOS:說明文字必須具體寫出「為什麼需要這個權限」。專案初期寫的是
Need Camera、Need Photo Library這類簡短文字,後來改成「需要您同意使用相機權限,用以拍攝照片及掃描 QR Code」這樣寫明用途的說法。 - Android:宣告了用不到、或範圍過大的權限,可能被退回。專案曾因 Android 的媒體讀取權限(
READ_MEDIA_IMAGES、READ_MEDIA_VIDEO)被退版,最後移除這兩項權限才重新送審。
權限規範還會跟著官方改變:Google 與 Apple 會隨著系統版本更新收緊權限政策。例如 Android 13 起,舊的 READ_EXTERNAL_STORAGE 改由更細分的媒體權限取代;Google Play 後來又進一步要求,不是核心需要大量存取相簿的 App,應改用系統的照片選擇器,而不是申請整個相簿的讀取權限。
也就是說,今天能過審的設定,明年不一定能過。這類變動不會出現在 package.json 的套件更新裡,只能留意官方公告,或是在送審被退時才發現。
4.3 原生環境:升級套件後 Android 打包失敗
現象:把 @capacitor/device 升到 7.0.0 後,Android 無法打包。
原因:新版要求 JDK 21,但專案的 Capacitor 6 環境不支援。這類錯誤由 Gradle 輸出,訊息冗長且偏原生領域,前端工程師不容易看懂。
解法:降回與 Capacitor 6 相容的 5.0.8。這也是 3.3 提到的版本問題的典型例子。
4.4 跨環境:同一個彈窗,電腦和手機上高度不一樣
現象:彈窗設定開到 70% 高,手機上正確,在電腦瀏覽器上卻明顯偏矮。
原因:共用彈窗元件裡同時存在四套高度規則,其中一套只在電腦上生效,並蓋掉了其他三套。而日常開發都在電腦上進行,等於一直看著和真機不同的畫面。
解法:統一規則:「有設定彈出比例的就是底部彈窗,高度只看那個數字」,不再受裝置判斷影響。
五、AI 模型帶來的轉變
5.1 專案初期:AI 還不夠強的時候
專案初期,AI 模型的能力還有限。遇到問題時,就算查資料、問 ChatGPT、問 Gemini,仍然要花很大的心力去研究和測試:
- 模擬器重現不了實機問題,只能一次次打包、裝到手機上測。
- 實機要怎麼除錯、怎麼調整,本身就是一門學問。
- 蘋果與安卓的行為差異,常常一邊修好、另一邊又壞了。
- 社群套件的版本合不合用,也要自己一個個試。
網路上的資料也有不少問題:很多是 Ionic 舊版本的寫法、有些問題只有人問沒人答、有些回答只說「我這樣改就好了」卻沒有解釋原因,照搬過來往往不適用。
老實說,那時的感覺就是在寫一個自己看不太懂的東西。畫面是網頁,我們看得懂;但相機、推播、鍵盤這些功能,背後是手機原生語言在執行,出了問題我們讀不懂。能做的只有片段式地問 AI、不停尋找可用的解法,花了很多時間,結果也不一定盡善盡美,有時甚至不太理想。修完之後,還要再花時間向團隊解釋、溝通為什麼這樣改。
5.2 近一年:Claude Code 變強之後
近一年,Claude Code 的模型能力明顯提升,帶來幾個關鍵改變。
(1)看不懂原生程式碼的困境,難度大幅下降
這是最大的改變。過去最卡的就是「原生端到底寫了什麼」。現在可以讓 Claude Code 直接讀取 App 專案資料夾裡的原生程式碼與 log,分析問題、找出原因並修正。
像 4.2 的權限設定,iOS 的 Info.plist、Android 的 AndroidManifest.xml 過去都是「照著文件貼上去、能動就好」,現在可以請 AI 逐項解釋每個設定的作用、哪些權限其實用不到。下方 (3) 的 iOS 小工具更是如此:Swift 程式、App Group、entitlements 這些前端團隊完全陌生的東西,都是由 AI 讀懂原生專案結構後撰寫的。
解法不再取決於「有沒有人剛好遇過」,只要程式碼讀得到,問題就有機會被分析出來。
(2)分工變得清楚:AI 分析除錯,人工實機驗證
Claude Code 目前還無法操作 Xcode、Android Studio 這類編譯工具,模擬器與實機的操作仍然需要手動。
所以現在的分工是:由模型讀取、分析、除錯,再由人在實機上測試功能是否符合需求。AI 也能協助寫驗證工具,例如曾為了驗證 Android 的長按手勢,寫了從電腦操控 Android 實機的腳本,讓原本只能人工點按的測試可以重複執行。
(3)簡單的功能可以自己刻
過去社群沒有套件就做不到。現在若是簡單的原生功能,可以參考社群上現有的套件,請 AI 協助自己刻一份。這樣比較不會受制於套件的版本相容問題,但代價是未來要自行維護。
實例:iOS 桌面小工具(Widget)
專案曾評估在 iOS 桌面加上小工具,顯示使用者當天的排程。盤點社群套件後發現:
- 主流、維護活躍的套件都要求 Capacitor 7 或 8,專案是 Capacitor 6,無法直接安裝。
- 唯一支援 Capacitor 6 的舊版套件,已經兩年多沒有更新。
- 若為此升級 Capacitor,牽涉約 20 個 Plugin(含幾個舊的 Cordova Plugin),等於一次大規模的回歸測試。
進一步分析後也發現,這些套件做的事其實很少:只是把 iOS 的「共享儲存空間」與「通知小工具重畫」兩個 API 包起來,核心不到百行 Swift。小工具本身的畫面,無論用不用套件,都必須用 SwiftUI 原生撰寫。
因此最後選擇不裝套件,自己寫一支 Capacitor 自訂 Plugin:
- 由 AI 參考社群套件的架構,撰寫約 60 行的 Swift Plugin,負責把網頁端整理好的資料寫入共享空間,並通知小工具更新。
- 小工具畫面以 SwiftUI 撰寫,支援小、中、大三種尺寸與深色模式。
- 資料與 App 首頁共用同一支 API 與同一組整理邏輯,避免兩邊顯示的筆數或排序對不上。
- 在離開 App、回到 App、登入與切換公司時更新資料,登出時清空。
開發過程中也踩到原生環境的版本問題:Xcode 26 產生的新版專案格式,CocoaPods 無法解析,導致建置失敗,最後改回舊版格式解決——正是 3.3 提到的情況。
對一個看不懂 Swift 的前端團隊來說,這在過去幾乎是不可能獨立完成的事。
(4)從單點修正到全面分析
使用者回報的通常是「某個地方怪怪的」。AI 會沿著問題往下追,像 4.4 的彈窗高度問題,最後發現是共用元件裡四套規則互相打架,一次統一處理,而不是一個彈窗一個彈窗去調。改共用元件前,也會先列出所有受影響的檔案,降低「改 A 壞 B」的風險。
(5)經驗能被保留下來
過去一個難解的問題修好了,知識只留在處理的人腦中。現在每次修正的原因與做法都會寫進 commit 說明與程式註解;團隊開發規範也整理成文件,讓人和 AI 都依循同一套標準。
5.3 仍然存在的限制
- 無法取代實機測試:觸控手感、鍵盤行為、不同機型的表現,仍需人工在裝置上確認。
- 修正方向也可能出錯:AI 降低了嘗試的成本,但不代表每次都對,改完仍要驗證。
- 需要先建立規範:沒有告訴它專案已經有自己的元件,它就可能直接用 Ionic 原生元件,造成寫法不一致。
- 決策仍由人負責:AI 可以提出方案,但哪個適合目前的專案與時程,需要人來判斷。
六、心得結論
Ionic 讓前端團隊能用一份程式碼同時支援 Web、iOS 與 Android,在開發效率與人力成本上有明顯的優勢。但它說到底不是原生:樣式客製化受限、原生功能依賴社群套件、原生環境的版本問題也不容易掌握,對於非常依賴原生功能的專案,可能不是最好的選擇。
過去遇到原生端的問題,只能靠社群和片段式的詢問,花大量時間嘗試,結果也未必理想。近一年 AI 模型變強之後,最大的困境——看不懂原生程式碼——難度下降了許多。由模型讀取、分析、除錯,再由人工在實機驗證,問題解決的方式有了根本上的改變。
當然,這不代表沒有代價。實機測試仍然要人工進行,自己刻的功能也要自己維護,開發與維護成本雖然降低了,但並沒有消失。
但瑕不掩瑜。至少現在,有模型協助把關程式,我們不再是在寫一個自己看不懂的東西。
