Loadding..

Debug Web Mobile trên macOS — Hướng dẫn đầy đủ iOS & Android

Debug Web Mobile trên macOS — Hướng dẫn đầy đủ iOS & Android

Tài liệu tổng hợp toàn bộ cách setup môi trường debug web trên iOS và Android từ máy Mac — cho cả trường hợp có device thật và không có device (dùng simulator/emulator).

debug web mobile macos

Mục lục

  1. Tổng quan các phương án
  2. iOS — có device thật
  3. iOS — không có device (Simulator)
  4. Android — có device thật
  5. Android — không có device (Emulator)
  6. Debug ngay trên màn hình mobile (eruda / vConsole)
  7. Truy cập localhost từ thiết bị mobile
  8. Tích hợp vào WordPress
  9. Device farm trên cloud
  10. Xử lý sự cố thường gặp
  11. Cheatsheet lệnh

1. Tổng quan các phương án

Phương ánNền tảngCần device?DevTools đầy đủĐộ chính xác
Safari Web InspectoriOSCao nhất
iOS Simulator + SafariiOSKhôngCao (thiếu perf thật)
Chrome chrome://inspectAndroidCao nhất
Android Emulator (AVD)AndroidKhôngCao (stock Android)
eruda / vConsoleCả haiKhông quan trọng⚠️ Rút gọnTrung bình
BrowserStack / LambdaTestCả haiKhôngCao (device thật)

Nguyên tắc chọn:

  • Debug logic JS, network, DOM → dùng remote DevTools (Safari / Chrome inspect).
  • Test nhanh trên máy người khác, staging, hoặc không cắm được cáp → eruda.
  • Test bug riêng của Samsung Internet, MIUI, iOS đời cũ → device farm cloud.

2. iOS — có device thật

2.1. Bật Web Inspector trên iPhone/iPad

Cài đặt (Settings)
  → Apps → Safari          (iOS 18+; iOS cũ hơn: Settings → Safari)
  → Nâng cao (Advanced)
  → Bật "Web Inspector"

2.2. Bật Develop menu trên Safari (macOS)

Safari → Settings (⌘,)
  → Advanced
  → Tích "Show features for web developers"

Sau bước này thanh menu sẽ xuất hiện mục Develop.

2.3. Kết nối và inspect

  1. Cắm iPhone vào Mac bằng cáp USB/USB-C.
  2. Trên iPhone hiện popup “Trust This Computer?” → chọn Trust, nhập passcode.
  3. Mở tab web cần debug trên Safari của iPhone.
  4. Trên Mac: Develop → [Tên iPhone] → [Tên tab].
  5. Cửa sổ Web Inspector mở ra với đầy đủ Console, Network, Elements, Sources, Storage.

2.4. Debug qua WiFi (không cần cáp)

Sau khi đã kết nối bằng cáp ít nhất 1 lần:

Safari → Develop → [Tên iPhone] → Connect via Network

Rút cáp ra, thiết bị vẫn hiện trong menu Develop khi cùng mạng WiFi.

2.5. Giới hạn cần biết

  • Chỉ debug được Safari và WKWebView. Chrome/Firefox/Edge trên iOS thực chất là vỏ bọc WebKit nhưng không expose qua Web Inspector.
  • App trong WebView (React Native, Capacitor, Cordova) debug được nếu build ở chế độ debug.
  • iOS 16.4+ hỗ trợ inspect cả SFSafariViewController.

3. iOS — không có device (Simulator)

3.1. Cài Xcode

Cách 1 — App Store (đơn giản nhất, ~10GB):

Mở App Store → tìm "Xcode" → Install

Cách 2 — Homebrew:

brew install --cask xcode

Sau khi cài, chạy 1 lần để accept license:

sudo xcodebuild -license accept
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

3.2. Mở Simulator

open -a Simulator

Hoặc từ Xcode: Xcode → Open Developer Tool → Simulator.

Chọn model thiết bị: File → Open Simulator → iOS 18.x → iPhone 16 Pro (hoặc model cần test).

3.3. Tải thêm phiên bản iOS cũ

Xcode → Settings → Components → iOS Simulator Runtimes → dấu "+"

Rất hữu ích khi cần tái hiện bug chỉ xảy ra trên iOS 15/16.

3.4. Inspect Simulator từ Safari

Simulator được nhận diện y hệt device thật:

Safari → Develop → Simulator (iPhone 16 Pro) → [tab đang mở]

Không cần bật Web Inspector thủ công trên simulator — mặc định đã bật.

3.5. Thao tác hữu ích với Simulator

Thao tácCách làm
Xoay màn hình⌘ + ← / ⌘ + →
Chụp màn hình⌘ + S
Quay video⌘ + R
Về Home⌘ + Shift + H
Mở URL trực tiếpKéo thả URL vào cửa sổ, hoặc xcrun simctl openurl booted "https://..."
Xoá dữ liệu SafariSimulator → Device → Erase All Content and Settings
Giả lập vị tríFeatures → Location → Custom Location

3.6. Điều khiển Simulator bằng CLI

# Liệt kê device
xcrun simctl list devices

# Boot 1 device cụ thể
xcrun simctl boot "iPhone 16 Pro"

# Mở URL trong Safari của simulator đang chạy
xcrun simctl openurl booted "http://localhost:5173"

# Chụp màn hình
xcrun simctl io booted screenshot ~/Desktop/shot.png

# Tắt tất cả
xcrun simctl shutdown all

3.7. Hạn chế của Simulator

  • Không phản ánh đúng hiệu năng thật (Simulator chạy trên CPU của Mac, nhanh hơn iPhone thật).
  • Không test được: camera, Bluetooth, cảm biến vân tay thật, push notification thật.
  • Một số bug về memory và rendering chỉ xuất hiện trên device thật.

4. Android — có device thật

4.1. Bật Developer Options trên điện thoại

Settings → About phone
  → Bấm "Build number" 7 lần liên tiếp
  → Nhập PIN nếu được hỏi
  → Hiện thông báo "You are now a developer!"

Với Xiaomi/MIUI: bấm vào MIUI version 7 lần. Với Samsung: Settings → About phone → Software information → Build number.

4.2. Bật USB Debugging

Settings → System → Developer options
  → Bật "USB debugging"

Xiaomi cần bật thêm USB debugging (Security settings).

4.3. Cài platform-tools trên Mac

brew install --cask android-platform-tools

Kiểm tra:

adb devices

Kết quả mong đợi:

List of devices attached
R5CT30XXXXX     device

Nếu hiện unauthorized → nhìn màn hình điện thoại, chấp nhận popup “Allow USB debugging?” và tích Always allow from this computer.

4.4. Inspect từ Chrome trên Mac

  1. Mở Chrome trên Mac → truy cập chrome://inspect/#devices
  2. Tích Discover USB devices
  3. Mở tab web cần debug trên Chrome của điện thoại
  4. Tab sẽ hiện trong danh sách → bấm inspect

DevTools mở ra kèm màn hình mirror của điện thoại (Screencast).

4.5. Debug qua WiFi

Cách 1 — Wireless debugging (Android 11+, không cần cáp):

Điện thoại: Developer options → Wireless debugging → Bật
  → "Pair device with pairing code"

Trên Mac:

adb pair 192.168.1.50:41234       # nhập IP:port hiện trên điện thoại
# Nhập pairing code 6 số

adb connect 192.168.1.50:5555     # port trong màn hình Wireless debugging

Cách 2 — Qua cáp trước rồi chuyển sang WiFi:

adb tcpip 5555
adb connect 192.168.1.50:5555
# Rút cáp, adb devices vẫn thấy thiết bị

4.6. Port forwarding — truy cập localhost của Mac

Trong chrome://inspect/#devices → Port forwarding… → thêm:

Device portLocal address
5173localhost:5173
8080localhost:8080

Trên điện thoại vào http://localhost:5173 là ra dev server của Mac. Cách này hoạt động qua cáp USB, không phụ thuộc WiFi.

4.7. Debug các trình duyệt khác

Trình duyệtCó inspect được?Ghi chú
Chrome Androidchrome://inspect
Edge Androidedge://inspect trên Edge desktop
Samsung InternetHiện trong chrome://inspect (cần bật Developer mode trong app)
Firefox Androidabout:debugging trên Firefox desktop
WebView trong appCần app build debug + setWebContentsDebuggingEnabled(true)

5. Android — không có device (Emulator)

5.1. Phương án A — Android Studio (đầy đủ, dễ dùng)

brew install --cask android-studio

Mở Android Studio → bỏ qua wizard tạo project → More Actions → Virtual Device Manager.

Tạo AVD:

  1. Bấm Create Device
  2. Chọn phần cứng: Pixel 7 hoặc Pixel 8 (kích thước phổ biến)
  3. Chọn System Image:
    • Mac Apple Silicon (M1/M2/M3/M4) → chọn tab ARM Images, ví dụ UpsideDownCake / API 34 / arm64-v8a
    • Mac Intel → chọn x86_64
    • Bắt buộc chọn bản có “Google APIs” hoặc “Google Play” để có sẵn Chrome
  4. Tinh chỉnh: RAM 2048MB+, Graphics = Hardware – GLES 2.0
  5. Finish → bấm ▶ để chạy

⚠️ Chọn sai kiến trúc (x86 trên máy M-series) sẽ khiến emulator cực chậm hoặc không boot được.

5.2. Phương án B — Command line tools (nhẹ, ~1GB)

Nếu không cần IDE:

brew install --cask android-commandlinetools

Thêm biến môi trường vào ~/.zshrc:

export ANDROID_HOME="$HOME/Library/Android/sdk"
export PATH="$PATH:$ANDROID_HOME/emulator:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin"
source ~/.zshrc

Cài thành phần cần thiết:

# Xem danh sách system image có sẵn
sdkmanager --list | grep system-images

# Cài (Apple Silicon)
sdkmanager "emulator" "platform-tools" "platforms;android-34" \
           "system-images;android-34;google_apis;arm64-v8a"

# Cài (Intel Mac)
sdkmanager "emulator" "platform-tools" "platforms;android-34" \
           "system-images;android-34;google_apis;x86_64"

# Chấp nhận license
sdkmanager --licenses

Tạo và chạy AVD:

avdmanager create avd -n pixel7 \
  -k "system-images;android-34;google_apis;arm64-v8a" \
  -d "pixel_7"

emulator -avd pixel7

Liệt kê AVD đã tạo:

emulator -list-avds
avdmanager list avd

5.3. Inspect Emulator từ Chrome

Emulator được adb nhận diện tự động:

adb devices
# emulator-5554   device

Mở chrome://inspect/#devices trên Chrome của Mac → tab của emulator hiện ra → inspect.

Không cần bật USB debugging thủ công (emulator đã bật sẵn).

5.4. ⭐ Truy cập localhost của Mac từ Emulator

Đây là điểm dễ nhầm nhất:

Muốn truy cậpĐịa chỉ dùng trong emulator
127.0.0.1 / localhost của Mac10.0.2.2
localhost của chính emulator127.0.0.1
Router / gateway ảo10.0.2.1
DNS của emulator10.0.2.3

Ví dụ dev server chạy http://localhost:5173 trên Mac → trong emulator mở http://10.0.2.2:5173.

Hoặc dùng adb reverse (giống port forwarding, dùng được localhost như bình thường):

adb reverse tcp:5173 tcp:5173
# Giờ trong emulator vào http://localhost:5173 là chạy

5.5. Extended Controls — mô phỏng điều kiện thật

Bấm nút ... cạnh cửa sổ emulator:

MụcDùng để
CellularGiả lập 2G/EDGE/3G/LTE, latency cao → test loading state
LocationSet GPS giả, import file GPX/KML
BatteryTest hành vi khi pin yếu / charging
Display / RotateTest responsive, landscape
Settings → ScreenBật “Send keyboard shortcuts to”

5.6. Thao tác hữu ích

# Cài APK
adb install app.apk

# Copy file vào emulator
adb push ./image.jpg /sdcard/Download/

# Mở URL trực tiếp trong Chrome của emulator
adb shell am start -a android.intent.action.VIEW -d "http://10.0.2.2:5173"

# Chụp màn hình
adb exec-out screencap -p > ~/Desktop/shot.png

# Quay video
adb shell screenrecord /sdcard/demo.mp4    # Ctrl+C để dừng
adb pull /sdcard/demo.mp4 ~/Desktop/

# Xem log hệ thống (lọc log của Chrome/WebView)
adb logcat | grep -i chromium

# Xoá dữ liệu Chrome trong emulator
adb shell pm clear com.android.chrome

Kéo thả file APK hoặc ảnh trực tiếp vào cửa sổ emulator cũng hoạt động.

5.7. Hạn chế của Emulator

  • Chỉ có stock Android + Chrome. Không tái hiện được bug riêng của Samsung Internet, MIUI Browser, hay skin của hãng.
  • Hiệu năng khác device thật (thường nhanh hơn).
  • Một số API phần cứng (camera thật, NFC, sinh trắc học) không đầy đủ.

6. Debug ngay trên màn hình mobile (eruda / vConsole)

Dùng khi: không cắm được cáp, test trên máy người khác, kiểm tra nhanh trên staging/production.

6.1. eruda (khuyến nghị)

<script src="https://cdn.jsdelivr.net/npm/eruda"></script>
<script>eruda.init();</script>

Xuất hiện nút tròn nổi trên màn hình, mở ra panel có: Console, Elements, Network, Resources, Sources, Info.

Chỉ bật khi có query string ?debug=1:

<script>
if (new URLSearchParams(location.search).has('debug')) {
  const s = document.createElement('script');
  s.src = 'https://cdn.jsdelivr.net/npm/eruda';
  s.onload = () => eruda.init();
  document.body.appendChild(s);
}
</script>

Cài qua npm:

npm i -D eruda
if (import.meta.env.DEV) {
  import('eruda').then(({ default: eruda }) => eruda.init());
}

Plugin hữu ích:

<script src="https://cdn.jsdelivr.net/npm/eruda-dom"></script>
<script src="https://cdn.jsdelivr.net/npm/eruda-timing"></script>
<script>
  eruda.init();
  eruda.add(erudaDom);
  eruda.add(erudaTiming);
</script>

6.2. vConsole (của Tencent)

<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script>
<script>new VConsole();</script>

Nhẹ hơn eruda, giao diện đơn giản hơn, mạnh về log network và system info.

6.3. So sánh

erudavConsole
Kích thước~110KB~70KB
Elements inspector✅ Tốt⚠️ Cơ bản
Network
Plugin system✅ Phong phú✅ Có
Chỉnh sửa DOM live

7. Truy cập localhost từ thiết bị mobile

7.1. Cùng mạng WiFi — dùng IP LAN

Lấy IP của Mac:

ipconfig getifaddr en0        # WiFi
ipconfig getifaddr en1        # Ethernet / adapter

Chạy dev server với --host để bind ra ngoài 127.0.0.1:

# Vite
npm run dev -- --host

# Next.js
next dev -H 0.0.0.0

# PHP built-in server
php -S 0.0.0.0:8080

# Python
python3 -m http.server 8080 --bind 0.0.0.0

Trên điện thoại vào http://192.168.1.20:5173.

⚠️ macOS Firewall có thể chặn. Vào System Settings → Network → Firewall → Options và cho phép ứng dụng (node/php) nhận kết nối đến.

7.2. Cần HTTPS hoặc mạng khác — dùng tunnel

Nhiều API web (Service Worker, getUserMedia, Geolocation, Clipboard) bắt buộc secure context. IP LAN dạng http://192.168.x.x không được coi là secure → phải dùng tunnel HTTPS.

Cloudflare Tunnel (miễn phí, không cần đăng ký):

brew install cloudflared
cloudflared tunnel --url http://localhost:8080
# → https://random-words-1234.trycloudflare.com

ngrok:

brew install ngrok
ngrok config add-authtoken <token>
ngrok http 8080

ngrok có sẵn web inspector tại http://localhost:4040 để xem lại toàn bộ request/response.

localtunnel:

npx localtunnel --port 8080

7.3. HTTPS cho local dev (không cần tunnel)

brew install mkcert
mkcert -install
mkcert localhost 192.168.1.20

Với Vite:

// vite.config.js
import fs from 'fs';

export default {
  server: {
    host: true,
    https: {
      key: fs.readFileSync('./192.168.1.20-key.pem'),
      cert: fs.readFileSync('./192.168.1.20.pem'),
    },
  },
};

Cần cài root CA của mkcert vào điện thoại (gửi file rootCA.pem qua AirDrop/email rồi cài trong Settings → Profile).

7.4. Bảng tóm tắt địa chỉ

Môi trườngĐịa chỉ trỏ về Mac
iOS Simulatorlocalhost / 127.0.0.1 (chung host)
iPhone thậtIP LAN (192.168.x.x) hoặc tunnel
Android Emulator10.0.2.2 hoặc adb reverse
Android thật (cáp)localhost sau khi adb reverse / port forwarding
Android thật (WiFi)IP LAN hoặc tunnel

8. Tích hợp vào WordPress

8.1. Nhúng eruda có điều kiện

Thêm vào functions.php của theme (hoặc plugin riêng):

add_action( 'wp_enqueue_scripts', function () {
    // Chỉ bật khi có ?debug=1 trên URL
    if ( ! isset( $_GET['debug'] ) ) {
        return;
    }

    // Chỉ cho user đã đăng nhập có quyền quản trị
    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    wp_enqueue_script(
        'eruda',
        'https://cdn.jsdelivr.net/npm/eruda',
        [],
        null,
        false
    );

    wp_add_inline_script( 'eruda', 'eruda.init();' );
}, 100 );

Truy cập https://site.com/?debug=1 khi đã đăng nhập admin để bật panel.

8.2. Bật WP debug log

Trong wp-config.php:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );      // ghi ra wp-content/debug.log
define( 'WP_DEBUG_DISPLAY', false ); // không in ra màn hình
define( 'SCRIPT_DEBUG', true );      // dùng file JS/CSS chưa minify
@ini_set( 'display_errors', 0 );

Theo dõi log realtime:

tail -f wp-content/debug.log

8.3. Truy cập site local từ mobile

LocalWP: có sẵn tính năng Live Link — bấm nút “Enable” trong tab Overview, nhận URL public HTTPS ngay.

Với wp-env / Docker: dùng cloudflared tunnel như mục 7.2.

Lưu ý: WordPress lưu siteurl và home trong database, truy cập bằng IP/domain khác sẽ bị redirect về domain gốc. Khắc phục bằng cách thêm vào wp-config.php:

define( 'WP_HOME',    'http://' . $_SERVER['HTTP_HOST'] );
define( 'WP_SITEURL', 'http://' . $_SERVER['HTTP_HOST'] );

Chỉ dùng dòng trên ở môi trường local/dev, tuyệt đối không đưa lên production.


9. Device farm trên cloud

Dùng khi cần test trên thiết bị/OS mà mình không có, hoặc trình duyệt của hãng (Samsung Internet, MIUI Browser).

Dịch vụFree tierDevTools thậtGhi chú
BrowserStack LiveCó (giới hạn phút)Nhiều device nhất, có tunnel cho localhost
LambdaTestRẻ hơn, UI gọn
Sauce LabsTrialMạnh về automation
Firebase Test LabCó quota free⚠️Chủ yếu cho app, không tiện cho web

Cả BrowserStack và LambdaTest đều có tool tunnel (BrowserStackLocalLT) để test được localhost của Mac trên device cloud.


10. Xử lý sự cố thường gặp

iOS

Vấn đềCách xử lý
Develop menu không hiệnSafari → Settings → Advanced → tích “Show features for web developers”
iPhone không hiện trong DevelopKiểm tra Web Inspector đã bật; rút cắm lại cáp; đổi cáp (cáp sạc rẻ có thể không truyền data)
Đã Trust nhưng vẫn không thấyReset trust: iPhone → Settings → General → Transfer or Reset → Reset Location & Privacy
Simulator không hiệnChạy xcrun simctl list devices xem có device nào ở trạng thái Booted không
Web Inspector trắng / không loadĐóng cửa sổ inspector, restart Safari trên cả 2 máy

Android

Vấn đềCách xử lý
adb devices báo unauthorizedNhìn màn hình điện thoại, chấp nhận popup RSA. Nếu không hiện: adb kill-server && adb start-server
adb devices trốngĐổi cáp; chọn chế độ USB = File Transfer (MTP) thay vì Charging only
chrome://inspect trống dù adb devices cóKiểm tra Chrome trên điện thoại đã mở tab; thử adb kill-server rồi restart Chrome desktop
Emulator chạy cực chậmSai kiến trúc image (x86 trên Apple Silicon). Tạo lại AVD với arm64-v8a
Emulator không bootTăng RAM lên 2048MB+; đổi Graphics sang “Software”; xoá ~/.android/avd/<name>.avd/*.lock
10.0.2.2 không truy cập đượcDev server phải bind 0.0.0.0, không phải 127.0.0.1. Hoặc dùng adb reverse
sdkmanager báo lỗi Javabrew install --cask temurin rồi set JAVA_HOME

Chung

Vấn đềCách xử lý
Truy cập IP LAN bị timeoutmacOS Firewall chặn → System Settings → Network → Firewall → Options → allow node/php
Service Worker không đăng kýCần HTTPS. Dùng cloudflared hoặc mkcert
CSS/JS bị cache cũ trên mobileTrong DevTools bật “Disable cache”; hoặc thêm query ?v=<timestamp>
Bug chỉ xảy ra trên device thậtĐúng — dùng device farm hoặc mượn máy để xác nhận

11. Cheatsheet lệnh

Setup ban đầu (chạy 1 lần)

# Android
brew install --cask android-platform-tools
brew install --cask android-studio          # hoặc android-commandlinetools

# iOS
brew install --cask xcode
sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

# Tunnel & HTTPS
brew install cloudflared mkcert
mkcert -install

Hằng ngày — iOS

open -a Simulator                                   # mở simulator
xcrun simctl list devices                           # xem device
xcrun simctl boot "iPhone 16 Pro"                   # boot device
xcrun simctl openurl booted "http://localhost:5173" # mở URL
xcrun simctl io booted screenshot ~/Desktop/s.png   # chụp màn hình
xcrun simctl shutdown all                           # tắt hết

Hằng ngày — Android

emulator -list-avds                    # xem AVD
emulator -avd pixel7 &                 # chạy emulator nền
adb devices                            # kiểm tra kết nối
adb reverse tcp:5173 tcp:5173          # map localhost
adb shell am start -a android.intent.action.VIEW -d "http://localhost:5173"
adb logcat | grep -i chromium          # xem log
adb kill-server && adb start-server    # reset khi lỗi

Dev server + tunnel

ipconfig getifaddr en0                 # lấy IP Mac
npm run dev -- --host                  # Vite bind 0.0.0.0
cloudflared tunnel --url http://localhost:5173

URL cần nhớ

chrome://inspect/#devices          → Chrome desktop, debug Android
edge://inspect                     → Edge desktop
about:debugging                    → Firefox desktop
http://localhost:4040              → ngrok inspector

Quy trình khuyến nghị

Khi mới bắt đầu dự án:

  1. Setup Android Emulator (Pixel 7, API 34, arm64) + iOS Simulator (iPhone 16 Pro).
  2. Cấu hình dev server bind --host.
  3. Nhúng eruda có điều kiện ?debug=1.

Khi phát hiện bug trên mobile:

  1. Tái hiện trên Simulator/Emulator trước → nếu ra bug thì debug bằng DevTools đầy đủ.
  2. Nếu không tái hiện được → nghi ngờ bug đặc thù của device/browser hãng → dùng eruda trên máy thật hoặc device farm.
  3. Xác nhận fix trên cả 2 nền tảng trước khi deploy.

Tài liệu cập nhật: 07/2026 — macOS Sequoia, Xcode 16, Android Studio Ladybug

Print