eduardweb.
Navigație & StateAvansat#react-native#android#ios#deep-linking#expo-router

Deep Linking Universal cu Expo Router: De la Custom Schemes la Universal Links fără dureri de cap

De George Iliescu, 25 iul. 2026 · 11 vizualizări · 2 like-uri

Postat 25 iul. 2026
json
{
  "expo": {
    "name": "App Demo",
    "slug": "app-demo",
    "scheme": "myapp",
    "ios": {
      "bundleIdentifier": "ro.domeniu.app",
      "associatedDomains": [
        "applinks:domeniu.ro"
      ]
    },
    "android": {
      "package": "ro.domeniu.app",
      "intentFilters": [
        {
          "action": "VIEW",
          "autoVerify": true,
          "data": [
            {
              "scheme": "https",
              "host": "domeniu.ro",
              "pathPrefix": "/produs"
            }
          ],
          "category": ["BROWSABLE", "DEFAULT"]
        }
      ]
    }
  }
}

Dacă ai configurat vreodată deep linking manual în React Navigation v5 sau v6, știi ce coșmar era să mapezi manual fiecare rută din stivă. Cu Expo Router lucrurile s-au simplificat enorm datorită file-system routing-ului, dar când ajungi în producție și trebuie să pui cap la cap Universal Links pe iOS și App Links pe Android, tot te lovești de câteva ziduri specifice OS-urilor. Am trecut prin asta recent pe un proiect e-commerce cu vreo 14k utilizatori activi zilnic și am adunat câteva lecții pe care voiam să le las aici.

Custom Schemes vs Universal Links

Nu începe direct cu Universal Links dacă ești la faza de MVP sau prototip. O schemă custom gen myapp://produs/123 e extrem de ușor de configurat și funcționează instant pe ambele platforme. În schimb, are mari probleme de securitate: orice altă aplicație instalată pe telefon poate înregistra aceeași schemă myapp:// și îți poate intercepta intent-urile.

Pentru producție ai nevoie de Universal Links (iOS) și App Links (Android). Adică link-uri normale HTTPS (https://domeniu.ro/produs/123) care deschid aplicația dacă e instalată, iar dacă nu e, trimit userul pe site sau în Store. Trade-off-ul e că devii complet dependent de fișiere găzduite pe serverul tău web (apple-app-site-association și .well-known/assetlinks.json) și de validarea lor de către sistemul de operare.

Configurarea în Expo (app.json)

Marele avantaj cu Expo Router e că nu trebuie să atingi Xcode sau Android Studio pentru entitlements dacă folosești Development Builds sau EAS Build. Totul se rezolvă curat direct din app.json.

Pe Android, trebuie să specifici intentFilters cu autoVerify: true pentru ca OS-ul să verifice fișierul assetlinks.json de pe server la instalare. Pe iOS, adaugi domeniul în associatedDomains cu prefixul applinks:.

Capcanele din producție: Apple CDN și Android Verification

Aici am pierdut cel mai mult timp și am scos câțiva peri albi. iOS nu mai descarcă fișierul apple-app-site-association direct de pe serverul tău în mod default în producție, ci îl trece prin CDN-ul Apple. Dacă faci o modificare la AASA pe server, Apple poate păstra versiunea veche în cache până la 24 de ore. Am pățit să stăm 4 ore într-un call de debug crezând că avem un bug în codul de Expo Router, când de fapt CDN-ul Apple refuza să-și facă refresh.

Pe Android, dacă serverul tău returnează altceva decât status code 200 (de exemplu un redirect 301 către WWW) sau dacă header-ul Content-Type nu e application/json, App Links va eșua tăcut. Telefonul pur și simplu va deschide link-ul în Chrome fără să arunce vreun avertisment clar în logcat.

Pentru testare rapidă în dev, recomand CLI-ul npx uri-scheme. Îți economisește zeci de minute: npx uri-scheme open "https://domeniu.ro/produs/123" --android

Routing-ul efectiv în Expo Router

Partea bună e că odată ce OS-ul predă controlul aplicației, Expo Router rezolvă totul automat. Structura ta de fișiere precum app/produs/[id].tsx va intercepta URL-ul https://domeniu.ro/produs/123 și va pasa parametrul id direct în hook-ul useLocalSearchParams(), fără să mai scrii niciun rand de configurare de linking manuală.

Voi cum gestionați problema cu cache-ul de CDN la Apple pe iOS când schimbați rutele în producție? Folosiți mode=developer în entitlements pe build-uri interne sau aveți alt truc?

Răspunsuri 0

Se încarcă răspunsurile…

Loghează-te pentru a răspunde

Doar membrii comunității pot lăsa comentarii.