Conceptos básicos de configuración del proyecto
10 ejemplos para comenzar con la configuración del proyecto: 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para comenzar con la configuración del proyecto: 7 básicos y 3 intermedios.
Scaffold una app Expo con forma de producción con un pin explícito de SDK 57. La plantilla default@sdk-57 incluye Expo Router, TypeScript y los scripts CLI recomendados.
npx create-expo-app@latest MyApp --template default@sdk-57
cd MyApp
npm installConfirma el pin de SDK antes de añadir características:
{
"dependencies": {
"expo": "~57.0.4",
"react": "19.2.3",
"react-native": "0.86.0"
}
}Herramientas: Estos ejemplos están dirigidos a Expo SDK 57 (
expo~57.0.4), React Native 0.86.0 y React 19.2.3.
Un proyecto default@sdk-57 recién creado es un árbol pequeño y predecible - aprende estas rutas antes de añadir características o paquetes monorepo.
MyApp/
├── app/ # Pantallas y layouts de Expo Router
│ ├── _layout.tsx # Stack raíz / providers
│ ├── index.tsx # Ruta "/"
│ └── (tabs)/ # Grupo de pestañas (inicio de plantilla)
├── assets/ # Iconos, splash, imágenes referenciadas en config
├── app.config.ts # Manifiesto dinámico (nombre, ID de paquete, plugins)
├── package.json # Deps fijadas a SDK y scripts npm
├── tsconfig.json # Extiende expo/tsconfig.base
├── babel.config.js # Preset de Expo para Metro
├── metro.config.js # Entrada del bundler Metro (a menudo export por defecto)
└── node_modules/app/ reemplaza un solo App.tsx - los nombres de archivos se asignan a rutas (app/settings.tsx → /settings)app/_layout.tsx es el layout raíz: envuelve providers, fuentes y chrome de navegación aquíassets/ se hacen referencia por URI en app.config.ts (icon, splash) e importados en componentesios/ o android/ en modo managed puro - aparecen después de npx expo prebuild o una compilación de EASRelacionado: Plantillas de create-expo-app - cambios entre blank, tabs y bare-minimum | Estructura de carpetas para características - escalando más allá del árbol inicial
La versión del paquete expo es el contrato que cada otro módulo de Expo debe satisfacer.
{
"name": "my-app",
"version": "1.0.0",
"main": "expo-router/entry",
"private": true,
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web"
},
"dependencies": {
"expo": "~57.0.4",
"react": "19.2.3",
"react-native": "0.86.0"
}
}expo ~57.0.4 bloquea el proyecto a SDK 57 - mezclar módulos nativos de SDK 56 con expo de SDK 57 causa fallos de compilaciónmain: "expo-router/entry" conecta Metro al bootstrap de Expo Router en lugar de expo/AppEntry.jsnpx expo install los usa como línea base de compatibilidadnpm install luego npx expo-doctor antes de escribir código de característicasRelacionado: Plantillas de create-expo-app - conjuntos de dependencias específicos de plantilla | ../expo-platform/create-expo-app-quickstart.md - flags de scaffold y lista de verificación
Los scripts por defecto delegan en la CLI de Expo para que cada compañero de equipo use los mismos flags del dev-server.
{
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"lint": "expo lint",
"typecheck": "tsc --noEmit"
}
}# Variantes comunes de start - pasa flags después de --
npm run start -- --clear # invalida caché de Metro después de cambios de dependencias
npm run start -- --tunnel # comparte QR entre redes (más lento)
npm run start -- --dev-client # abre en una compilación de desarrollo personalizada
npm run ios # abreviatura para simuladorexpo start posee Metro, el menú de desarrollo y códigos QR - evita llamar a react-native start directamente en proyectos de Expoandroid, ios) son atajos; aún así lanzan Metro primero, luego abren el destinotypecheck temprano para que CI pueda gate merges sin una compilación nativa completanpx expo install <pkg> al añadir módulos nativos - lee la versión expo fijada y elige rangos semver compatiblesRelacionado: Mejores prácticas de configuración del proyecto - scripts que todo equipo debe estandarizar
Extiende la configuración base de TypeScript de Expo, luego aprieta verificaciones sin romper la resolución de rutas de Metro.
{
"extends": "expo/tsconfig.base",
"compilerOptions": {
"strict": true,
"noUncheckedIndexedAccess": true,
"paths": {
"@/*": ["./*"]
}
},
"include": [
"**/*.ts",
"**/*.tsx",
".expo/types/**/*.ts",
"expo-env.d.ts"
]
}extends: "expo/tsconfig.base" incluye el jsx correcto, moduleResolution y tipos de Expo Routerstrict: true atrapa bugs de nulabilidad temprano - los bloqueos móviles son más difíciles de depurar que los errores de consola webpaths con @/* coincide con alias de importación comunes; Metro lee la misma asignación vía tsconfigPaths en plantillas de Expo más nuevas.expo/types/**/*.ts para que las rutas tipadas generadas por Expo Router sean parte de tsc --noEmitRelacionado: ../typescript-rn/expo-router-typed-routes/expo-router-typed-routes.md - rutas tipadas generadas en
.expo/types
app.config.ts es la fuente única de verdad para identidad de app, iconos, permisos y plugins de configuración.
import { ExpoConfig, ConfigContext } from "expo/config";
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: "My App",
slug: "my-app",
version: "1.0.0",
orientation: "portrait",
icon: "./assets/icon.png",
scheme: "myapp",
userInterfaceStyle: "automatic",
newArchEnabled: true,
ios: {
supportsTablet: true,
bundleIdentifier: "com.example.myapp",
},
android: {
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#ffffff",
},
package: "com.example.myapp",
},
plugins: ["expo-router"],
experiments: {
typedRoutes: true,
},
});slug impulsa URLs del dashboard de Expo y canales de actualización - cámbialo deliberadamente junto con name e IDs de paquetescheme registra prefijos de deep-link consumidos por Expo Router y expo-linkingplugins se ejecutan en tiempo de prebuild - se ignoran en Expo Go cuando el plugin no está incluido en el clienteapp.config.ts sobre app.json cuando necesitas ramificación de entorno sin confirmar secretosRelacionado: ../expo-platform/expo-platform-basics/expo-platform-basics.md - flujo administrado y descripción general de config
Ejecuta expo-doctor después de cada scaffold, clon o bump de dependencia - compara tu gráfico con la base de datos de compatibilidad de SDK 57.
npx expo-doctor# Ruta de corrección típica cuando el doctor reporta skew de versión
npx expo install --fix
npx expo-doctorEjemplo de salida para actuar (no ignorar):
✖ expo-camera@15.0.0 - esperado ~17.0.0 para SDK 57
✖ react-native-reanimated@3.16.0 - esperado ~4.0.0 para SDK 57
› Ejecuta: npx expo install --fixexpo install --fix reescribe rangos de package.json a versiones compatibles con SDK sin adivinar semver manualmentemainRelacionado: ../expo-platform/upgrading-expo-sdk-versions/upgrading-expo-sdk-versions.md - bumps deliberados de SDK
Los configs de Metro y Babel son delgados en una app Expo estándar - mantenlos mínimos a menos que la resolución monorepo requiera cambios.
// babel.config.js
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
};
};// metro.config.js
const { getDefaultConfig } = require("expo/metro-config");
/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);
module.exports = config;babel-preset-expo habilita Reanimated, Expo Router y transformaciones de entorno esperadas por SDK 57getDefaultConfig de expo/metro-config establece resolver, transformer y extensiones de asset para el SDK fijadoexpowatchFolders de monorepo o resolvers personalizados - consulta la guía de paquetes compartidos antes de editarRelacionado: Paquetes compartidos y resolución de Metro -
watchFoldersy trampas de symlink
Un script de verificación corta atrapa skew de SDK, errores de TypeScript y errores de config antes de que nadie escriba código de características.
#!/usr/bin/env bash
# scripts/verify-first-run.sh
set -euo pipefail
echo "→ Comprobando pin de SDK..."
node -e "
const p = require('./package.json').dependencies;
const expected = { expo: '~57.0.4', react: '19.2.3', 'react-native': '0.86.0' };
for (const [k, v] of Object.entries(expected)) {
if (p[k] !== v) throw new Error(\`Se esperaba \${k}=\${v}, se obtuvo \${p[k]}\`);
}
console.log(' Pin de SDK OK');
"
echo "→ Ejecutando expo-doctor..."
npx expo-doctor
echo "→ Verificando tipos..."
npx tsc --noEmit
echo "→ Resolviendo config pública..."
npx expo config --type public | head -n 20
echo "✅ Las verificaciones de primera ejecución pasaron - ejecuta: npm run start"chmod +x scripts/verify-first-run.sh
./scripts/verify-first-run.shnpm install en cada clon nuevo - los lockfiles pueden ser correctos mientras la CLI global de un compañero es antigua@sdk-57expo config --type public confirma que plugins e IDs de paquete se resuelven - atrapa typos en app.config.ts tempranoRelacionado: ../expo-platform/create-expo-app-quickstart/create-expo-app-quickstart.md - script de scaffold de equipo reproducible
Rama la identidad de app en APP_VARIANT para que compilaciones de dev, staging y producción coexistan sin repos separados.
import { ExpoConfig, ConfigContext } from "expo/config";
const APP_VARIANT = process.env.APP_VARIANT ?? "development";
const bundleSuffix = APP_VARIANT === "production" ? "" : `.${APP_VARIANT}`;
export default ({ config }: ConfigContext): ExpoConfig => ({
...config,
name: APP_VARIANT === "production" ? "My App" : `My App (${APP_VARIANT})`,
slug: "my-app",
ios: {
bundleIdentifier: `com.example.myapp${bundleSuffix}`,
},
android: {
package: `com.example.myapp${bundleSuffix}`,
},
extra: {
appVariant: APP_VARIANT,
},
});# Lanza con una variante - nombre e ID de paquete cambian por comando
APP_VARIANT=development npx expo start
APP_VARIANT=staging npx expo run:ios
APP_VARIANT=production npx eas build --profile production --platform allAPP_VARIANT es una convención de equipo - Expo no lo define; la consistencia importa más que el nombre exactoextra para que el código runtime pueda gate logging, URLs base de API o feature flagsenv.APP_VARIANT por canal - evita hard-codear URLs en fuenteRelacionado: Múltiples apps en un repo - apps white-label y específicas de flavor | ../expo-platform/environments-and-eas-environment-variables/environments-and-eas-environment-variables.md - secretos por entorno
Confirma el lockfile y un .gitignore consciente de móvil el primer día - las instalaciones reproducibles importan para EAS y compañeros de equipo.
# dependencias
node_modules/
# Expo
.expo/
dist/
web-build/
# Nativo (flujo administrado - generado en build)
ios/
android/
# Secretos
.env
.env.*
!.env.examplegit init
git add .
git commit -m "chore: scaffold MyApp (default@sdk-57)"{
"engines": {
"node": ">=20.0.0"
}
}package-lock.json, yarn.lock o pnpm-lock.yaml) - EAS lo usa para reproducir instalaciones.expo/ - estado de dev local; no debería fusionarse entre máquinasios/ y android/ en flujo managed hasta que intencionalmente adoptes Continuous Native Generation (CNG) o flujo bareengines.node para que CI y laptops ejecuten el mismo Node major - la herramienta de SDK 57 espera Node 20+Relacionado: Monorepo con Turborepo - estrategia de lockfile cuando las apps comparten paquetes | Mejores prácticas de configuración del proyecto - convenciones que escalan más allá del primer sprint
Versiones de stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0 y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 16 jul 2026