new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo & React Native · all subjects

guides

835 notes in this subject, read out of this brain and free to use. This is page 8 of 14.

Server-side code removal with typeof window === 'undefined'

The pattern 'typeof window === "undefined"' is used to conditionally enable or disable code for server and client environments. When bundling for server environments, babel-preset-expo transforms this check to 'true'. By default, the check remains unchanged when bundling for web client environments. You can configure babel-preset-expo to enable this transform by passing '{ minifyTypeofWindow: true }', though this remains disabled by default for web environments since web workers do not have a window global. This transform runs in both development and production but only removes conditional requires in production.

Remove development-only code with process.env.NODE_ENV and __DEV__

To exclude development-only code from production bundles, use the process.env.NODE_ENV environment variable or the non-standard __DEV__ global boolean. Code wrapped in conditionals like 'if (process.env.NODE_ENV === "development")' or 'if (__DEV__)' will be removed from the production bundle after constants folding and minification. This optimization only runs in production builds; conditionals are kept in development builds.

Platform shaking removes platform-specific code

Expo CLI employs platform shaking during app bundling to create separate bundles for each platform (Android, iOS, web). Code that is used conditionally based on Platform.select or Platform.OS directly imported from react-native is removed from other platforms. This optimization is production-only and runs on a per-file basis. If Platform.OS is re-exported through a different module, it will not be removed during bundling. The process.env.EXPO_OS can be used to detect the platform the JavaScript was bundled for, but it does not support platform shaking imports due to how Metro minifies code.

EXPO_PUBLIC_ environment variables for custom code removal

EXPO_PUBLIC_ environment variables are inlined before the minification process and can be used to remove code from the production bundle. When a variable like EXPO_PUBLIC_DISABLE_FEATURE=true is set in the .env file, conditionals checking this variable (e.g., 'if (!process.env.EXPO_PUBLIC_DISABLE_FEATURE)') will be transformed to literals and then removed during minification. This system does not apply to server code, and library authors should not use EXPO_PUBLIC_ environment variables since they only run in application code for security reasons.

Enable experimental tree shaking in SDK 52-53

To enable experimental tree shaking in SDK 52-53 (enabled by default in SDK 54+), perform the following steps: (1) Ensure experimentalImportSupport is enabled in metro.config.js by setting config.transformer.getTransformOptions to return an object with transform.experimentalImportSupport: true. (2) Set environment variable EXPO_UNSTABLE_METRO_OPTIMIZE_GRAPH=1 in .env to keep modules around until the entire graph is created. (3) Set environment variable EXPO_UNSTABLE_TREE_SHAKING=1 in .env. (4) Bundle your app in production mode using 'npx expo export'. Both environment variables only apply in production mode.

experimentalImportSupport uses custom Babel plugin transform

Experimental import support uses a custom version of the @babel/plugin-transform-modules-commonjs plugin that drastically reduces the number of resolutions and simplifies the output bundle. This feature can be used with inlineRequires to further optimize the bundle experimentally.

Star exports automatically expanded with Expo tree shaking (SDK 52+)

With Expo tree shaking enabled (SDK 52+), star exports like 'export * from "./icons"' are automatically expanded and shaken based on usage. The optimization pass crawls the exported module and adds the exports to the current module; unused exports are removed from the production bundle. If the star export pulls in ambiguous exports such as module.exports.ArrowUp or exports.ArrowDown, the optimization pass will not expand the star export and no exports will be removed.

Recursive module optimization with Expo tree shaking (SDK 52+)

Expo tree shaking optimizes modules by recursing through the graph exhaustively to find unused imports. If a function is not used in the app, it is removed, and the module is scanned again to see if other exports used only by that function can be removed. This process recurses up to 5 times for a given module before bailing out due to performance reasons.

inlineRequires with Expo tree shaking in metro.config.js

When Expo tree shaking is enabled, you can safely enable inlineRequires in metro.config.js for production bundles to lazily load modules when they are evaluated, leading to faster startup time. This is configured by setting config.transformer.getTransformOptions to return an object with transform.experimentalImportSupport: true and transform.inlineRequires: true. Avoid using inlineRequires without Expo tree shaking as it can change the execution order of side-effects.

Sanity CMS with Visual Editing for Expo and React Native

Sanity is a CMS option that supports Visual Editing in Expo and React Native apps, with documentation available at https://www.sanity.io/docs/visual-editing/visual-editing-with-react-native.

Strapi CMS integration with Expo

Strapi is a CMS option available for Expo app integration, with documentation available at https://strapi.io/integrations/expo.

Benefits of using a CMS with Expo and React Native

Integrating a CMS into your Expo and React Native app lets you remotely manage and update content, push out new information to users instantly, and scale your content operations without releasing new app updates. Using a CMS can save you significant development time and enable non-technical users such as editors and marketers to update app content easily through a user-friendly interface.

What a Content Management System (CMS) is

A Content Management System (CMS) is a platform that allows you to create, manage, and organize digital content such as blog posts, images, and product information without the need to write custom backend code.

PostHog works with Expo Go

PostHog is compatible with Expo Go and can be integrated without requiring a development build.

Analytics requires development build with Expo Go

Most analytics SDKs require configuring custom native code. Native code is not configurable when using Expo Go. However, you can create a development build, which will allow you to use any analytics service.

Astrolytics works with Expo Go

Astrolytics is compatible with Expo Go and can be integrated without requiring a development build.

Aptabase works with Expo Go

Aptabase Analytics is compatible with Expo Go and can be integrated without requiring a development build.

Analytics services available in Expo ecosystem

The following analytics services are available for Expo and React Native projects: Google Firebase Analytics, Segment, Amplitude, AWS Amplify, Vexo, Aptabase (works with Expo Go), Astrolytics (works with Expo Go), PostHog (works with Expo Go), and Dreambase.

Clerk authentication guide available

Expo provides a guide for adding Clerk authentication and user management to Expo and React Native projects.

Google authentication configuration available

Expo provides a guide for configuring @react-native-google-signin/google-signin to add Google authentication in Expo projects.

Facebook authentication configuration available

Expo provides a guide for configuring react-native-fbsdk-next to add Facebook authentication in Expo projects.

BugSnag integration guide location

The official BugSnag integration guide for Expo apps is available at https://docs.bugsnag.com/platforms/react-native/expo/. It provides instructions for adding BugSnag to Expo apps to report JavaScript errors and includes instructions for uploading source maps for updates published with EAS Update.

BugSnag capabilities for Expo

BugSnag provides end-to-end error reporting and analytics for Expo apps. It supports React Native and offers features including release health dashboards, stability scores and targets, built-in alerts via email, Slack and PagerDuty, error grouping by root cause, business impact analysis, diagnostic data collection, full stacktraces, and automatic breadcrumbs for reproduction.

BugSnag source maps support for EAS Update

BugSnag supports uploading source maps for updates published with EAS Update, enabling proper error stack trace translation for published versions of Expo apps.

Server Function example with async function

Example Server Function defined inline: ```tsx export default function Index() { return ( <Button title="Press me" onPress={async () => { 'use server'; console.log('Button pressed'); return '...'; }} /> ); } ```

React Server Components experimental status

React Server Components in Expo Router are experimentally available as a beta release and subject to breaking changes. This is an early preview of a feature that will be enabled by default in Expo Router.

EAS Hosting for Server Components deployment

For web deployment, build the web project with 'npx expo export -p web' then host it locally with 'npx expo serve' or deploy to EAS Hosting. For native, deploy servers to EAS following the native deployment guide.

React Server Components prerequisites

To use React Server Components in Expo, you need a project using Expo Router and React Native New Architecture. React Native New Architecture is required and is enabled by default from SDK 52.

Request headers access in Server Components

You can access request headers using the 'unstable_headers' function from 'expo-router/rsc/headers' module. The function returns a promise that resolves to a read-only Headers object.

unstable_headers limitation with static rendering

The unstable_headers API cannot be used with build-time rendering (render: 'static') because headers dynamically change based on the request. In the future, this API will assert if the output mode is static.

Full React Server Components mode

Full React Server Components mode is experimental. In this mode, the default rendering mode for routes is server components instead of client components. Enable it with the reactServerComponentRoutes flag in app.json under expo.experiments alongside reactServerFunctions.

Full Server Components mode limitations

In full React Server Components mode: there is currently no stack routing, custom layouts (Stack, Tabs, Drawer) do not support Server Components yet, and most Link component props are not supported yet.

router.reload() for Server Components

In full React Server Components mode, you can manually trigger a reload using router.reload() from the useRouter hook to refetch data or re-render the component.

Build-time rendering with render: 'static'

The render: 'static' option in unstable_settings will render the component at build-time and never re-render it in production. This is similar to how classic static site generators work. Routes marked with static output will be rendered at build-time and embedded in the native binary, enabling rendering routes without making a server request.

Dynamic rendering default behavior

The current default rendering mode for React Server Components is 'dynamic', which renders the component at request-time and re-renders it on every request.

React Server Components known limitations

Known limitations include: Expo Snack does not support bundling Server Components; EAS Update does not work with Server Components yet; DOM components cannot use React Server Functions in production yet; production deployment is limited and not recommended; server rendering RSC payloads to HTML is not supported; generateStaticParams is only partially supported; HTML form integration with Server Functions is not supported; StyleSheet.create and Platform.OS are not supported on native (use standard objects and process.env.EXPO_OS instead); React Server Functions invoking other Server Functions are not supported on Hermes.

Library compatibility with Server Components

Not all libraries are optimized for React Server Components. You can use the 'use client' directive to mark a file as a Client Component and use it in a Server Component to workaround compatibility issues. Re-export each module individually rather than using 'export * from' as this breaks interoperability between server and client.

use client modules and dot-access limitation

Modules marked with 'use client' cannot be dot-accessed from Server Components. This means operations like StyleSheet.create or Platform.OS will not work on the server without further optimization in the react-native package.

React Suspense in Server Components

You can stream back partial UI from the server while waiting for data to load by using React Suspense. Each Suspense boundary can have its own fallback, allowing incremental UI updates as different async components resolve.

Suspense control of loading state

Using Suspense boundaries enables you to control the loading state incrementally. Without a Suspense wrapper around a component, the page waits for all components to finish rendering before updating the UI.

server-only module for security

You can use the 'server-only' module to ensure a module never runs on the client. Importing this module will assert if the module runs on the client.

Environment variables in Server Components

You can access environment variables using process.env in Server Components. Define secrets in the .env file. You do not need to restart the dev server to update environment variables as they are automatically reloaded on every request.

Server Components example with async data fetching

Example Server Component that fetches data from an API: ```tsx import 'server-only'; import { Image, Text, View } from 'react-native'; export async function Pokemon() { const res = await fetch('https://pokeapi.co/api/v2/pokemon/2'); const json = await res.json(); return ( <View style={{ padding: 8, borderWidth: 1 }}> <Text style={{ fontWeight: 'bold', fontSize: 24 }}>{json.name}</Text> <Image source={{ uri: json.sprites.front_default }} style={{ width: 100, height: 100 }} /> {json.abilities.map(ability => ( <Text key={ability.ability.name}>- {ability.ability.name}</Text> ))} </View> ); } ```

Client Component example with use client

Example Client Component: ```tsx 'use client'; import { Text } from 'react-native'; export default function Button({ title }) { return <Text onPress={() => {}}>{title}</Text>; } ```

Server Function standalone file example

Example Server Functions in standalone file: ```tsx 'use server'; export async function callAction() { // ... } ``` These can be imported and used in Client Components.

Server Function rendering example with profile

Example Server Function that renders components on the server: ```tsx 'use server'; import 'server-only'; import { View, Image, Text } from 'react-native'; export async function renderProfile({ username, accessToken, }: { username: string; accessToken: string; }) { const { name, image } = await fetch(`https://api.example.com/profile/${username}`, { headers: { Authorization: `Bearer ${accessToken}`, 'X-Secret': process.env.SECRET, }, }).then(res => res.json()); return ( <View> <Image source={{ uri: image }} /> <Text>{name}</Text> </View> ); } ```

Client Component invoking Server Function example

Example Client Component that invokes a Server Function: ```tsx 'use client'; import { useLocalSearchParams } from 'expo-router'; import * as React from 'react'; import { Text } from 'react-native'; import { renderProfile } from '@/components/server-actions'; function Fallback() { return <Text>Loading...</Text>; } export default function Profile() { const { username } = useLocalSearchParams(); const { accessToken } = useCustomAuthProvider(); const profile = React.useMemo( () => renderProfile({ username, accessToken }), [username, accessToken] ); return <React.Suspense fallback={<Fallback />}>{profile}</React.Suspense>; } ```

Library compatibility workaround example

Example workaround for libraries not optimized for Server Components: ```tsx 'use client'; export { One, Two, Three } from 'react-native-unoptimized'; ``` Use individual exports instead of 'export *' to avoid breaking interop between server and client.

Suspense streaming example with nested components

Example using Suspense to stream partial UI: ```tsx // app/index.tsx (Client Component) import { Suspense } from 'react'; import { renderMediumTask, renderExpensiveTask } from '@/actions/tasks'; export default function App() { return <Suspense fallback={<Text>Loading...</Text>}>{renderTasks()}</Suspense>; } // actions/tasks.tsx (Server Functions) 'use server'; export async function renderTasks() { return ( <Suspense fallback={<Text>Loading...</Text>}> <> <MediumTask /> <Suspense fallback={<Text>Loading...</Text>}> <ExpensiveTask /> </Suspense> </> </Suspense> ); } async function MediumTask() { await new Promise(resolve => setTimeout(resolve, 1000)); return <Text>Medium task done!</Text>; } async function ExpensiveTask() { await new Promise(resolve => setTimeout(resolve, 3000)); return <Text>Expensive task done!</Text>; } ```

Request headers access example

Example accessing request headers in Server Component: ```tsx import { unstable_headers } from 'expo-router/rsc/headers'; export async function renderHome() { const authorization = (await unstable_headers()).get('authorization'); return <Text>{authorization}</Text>; } ```

Full Server Components mode configuration

To enable full React Server Components mode: ```json { "expo": { "experiments": { "reactServerFunctions": true, "reactServerComponentRoutes": true } } } ```

router.reload() example

Example using router.reload() to reload Server Components: ```tsx 'use client'; import { useRouter } from 'expo-router'; import { Text } from 'react-native'; export function Button() { const router = useRouter(); return ( <Text onPress={() => { router.reload(); }}> Reload current route </Text> ); } ```

Static rendering configuration example

Example static rendering configuration: ```tsx import { Text, View } from 'react-native'; export const unstable_settings = { render: 'static', }; export default function Index() { return ( <View> <Text>Hello, world!</Text> </View> ); } ```

generateStaticParams example

Example generating static pages at build-time: ```tsx import { Text } from 'react-native'; export const unstable_settings = { render: 'static', }; export async function generateStaticParams() { return [{ shape: 'square' }]; } export default function ShapeRoute({ shape }) { return <Text>{shape}</Text>; } ```

CSS import in Server Components example

Example importing CSS in Server Components: ```tsx import './styles.css'; import styles from './styles.module.css'; export default function Index() { return <div className={styles.container}>Hello, world!</div>; } ```

Meta tags in Server Components example

Example using React 19 meta tags in Server Components: ```tsx export default function Index() { return ( <> {process.env.EXPO_OS === 'web' && ( <> <meta name="description" content="Hello, world!" /> <meta property="og:image" content="/og-image.png" /> </> )} <MyComponent /> </> ); } ```

Initial route with Suspense example

Example initial route using Client Component and Server Function with Suspense: ```tsx /// <reference types="react/canary" /> import React from 'react'; import { ActivityIndicator } from 'react-native'; import renderInfo from '../actions/render-info'; export default function Index() { return ( <React.Suspense fallback={ <ActivityIndicator /> }> {renderInfo({ name: 'World' })} </React.Suspense> ); } ```

Basic Server Function example

Example basic Server Function: ```tsx 'use server'; import { Text } from 'react-native'; export default async function renderInfo({ name }) { return <Text>Hello, {name}!</Text>; } ```

CSS import support in Server Components

Expo Router supports importing global CSS and CSS modules in Server Components (in full React Server Components mode). The CSS will be hoisted into the client bundle from the server.

generateStaticParams for build-time pages

You can generate static pages at build-time using the generateStaticParams function. This is useful for components that must only run at build-time and not on the server.

Give your agent this brain