Skip to main content

Working with Web Support

1. Configuring Web Settings

Property Values Description
web.build.output static Directory where the built web files are output.
web.build.publicUrl / Base URL for the built web application.
web.build.analyze false Enables bundle analysis tool for performance insights.
web.build.minify true Enables minification of the built files.
web.build.target es2020 JavaScript target version for the web build.

Example: Web Settings in app.json

{
  "expo": {
    "web": {
      "build": {
        "output": "dist",
        "publicUrl": "/my-app/",
        "analyze": true,
        "minify": false,
        "target": "es2020"
      }
    }
  }
}
Note: The web.build.publicUrl property is important for deploying to subdirectories or custom domains.

2. Running on Web Platform

Command Description Notes
expo start Starts the development server for web platform Automatically opens the web browser
expo start --web Starts the development server specifically for web Useful when you want to run only web
expo start --web-only Starts the web server without starting the mobile dev server Useful for isolated web development

Example: Running Expo on Web

expo start --web
Note: Expo Web support is built on top of React Native Web, which allows you to run your Expo project in a web browser.
Warning: Not all Expo APIs are supported on the web. Some features might not work as expected.

3. Building for Web

Command Description Notes
expo build:web Builds the Expo project for web deployment Requires a valid web configuration in app.json

Example: Building for Web

expo build:web
Note: The web build process uses webpack under the hood to bundle your app.

Web Build Configuration

  • web in app.json must define the web-specific configuration
  • Supports custom webpack configuration via webpack.config.js
  • Build artifacts are placed in the web-build directory

4. Using Web-Specific Code

Example: Conditional Web Code

import { Platform } from 'react-native';

if (Platform.OS === 'web') {
  // Web-specific logic
  const webSocket = new WebSocket('wss://example.com');
  const storage = localStorage;
} else {
  // Native logic
  const storage = await AsyncStorage.getItem('key');
}
Platform Access Method Notes
Web Platform.OS === 'web' Check for web environment
Native Platform.OS === 'ios' || Platform.OS === 'android' Check for mobile platforms
Note: Web-specific code should be isolated to avoid runtime errors on native platforms.

Example: Web-Only Component

import React from 'react';
import { Platform } from 'react-native';

const WebOnlyComponent = () => {
  if (Platform.OS !== 'web') {
    return null;
  }

  return (
    <div>
      <h2>Web-Only Content</h2>
      <p>This component only renders on web.</p>
    </div>
  );
};

export default WebOnlyComponent;

Web-Specific Considerations

  • Use Platform.OS === 'web' to detect web environment
  • Web-specific logic should be isolated to prevent runtime errors on native platforms
  • Some React Native APIs are not available on web (e.g., AsyncStorage)
  • Use browser APIs directly where appropriate (e.g., localStorage, WebSocket)

5. Configuring Webpack

Example: Basic Webpack Configuration

module.exports = {
  resolve: {
    extensions: ['.web.js', '.js', '.json']
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['@babel/preset-env', '@babel/preset-react']
          }
        }
      }
    ]
  }
}
Property Description Default
resolve.extensions File extensions to resolve in order ['.js', '.json']
module.rules Rules to process files []
Note: Expo uses .web.js extensions for web-specific code.
Warning: Make sure to exclude node_modules in your loaders to avoid performance issues.

6. Setting Favicon

Property Value Description
favicon string Path to the favicon file (e.g., ./assets/favicon.ico)

Example: Configuring Favicon in app.json

{
  "expo": {
    "name": "MyApp",
    "slug": "my-app",
    "favicon": "./assets/favicon.ico"
  }
}
Note: The favicon should be a square image in .ico, .png, or .svg format. For web builds, it will be used as the browser tab icon.

7. Implementing PWA Features

Feature Description Implementation
Service Worker Enables background processing and caching
// Register service worker in main.js
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw.js');
}
Manifest Defines app metadata for PWA installation
// In app.json
{
  "expo": {
    "web": {
      "splash": {
        "image": "./assets/splash.png"
      },
      "manifest": {
        "name": "MyApp",
        "short_name": "MyApp",
        "start_url": ".",
        "display": "standalone",
        "theme_color": "#000000"
      }
    }
  }
}
Push Notifications Enables push notifications via Firebase or Web Push API
// Using Expo Push Notifications
import * as Notifications from 'expo-notifications';

Notifications.setNotificationHandler({
  handleNotification: async () => ({
    shouldShowAlert: true,
    shouldPlaySound: false,
    shouldSetBadge: false,
  }),
});

const token = await Notifications.getExpoPushTokenAsync();
console.log(token.data);

Example: Adding PWA Support to Expo App

// app.json
{
  "expo": {
    "name": "MyPWAApp",
    "web": {
      "splash": {
        "image": "./assets/splash.png",
        "resizeMode": "contain",
        "backgroundColor": "#ffffff"
      },
      "output": "static",
      "build": {
        "outputDirectory": "dist"
      }
    }
  }
}
Note: PWA features require the web platform configuration in app.json.
Warning: Service workers must be registered from the root of your domain to function correctly in browsers.

8. Handling Responsive Design

Property Description Values Notes
width Defines the width of the element auto, 100%, 50px Can be set in pixels, percentages, or auto
height Defines the height of the element auto, 100%, 50px Can be set in pixels, percentages, or auto
flex Controls how a flex item grows or shrinks 0 1 auto, 1 Shorthand for flex-grow, flex-shrink, and flex-basis
maxWidth Defines the maximum width of an element 100%, 500px Prevents the element from growing beyond this value
minWidth Defines the minimum width of an element 100%, 200px Prevents the element from shrinking below this value
padding Space inside the element's border 10px, 5% Can be set in pixels, percentages, or ems
margin Space outside the element's border 10px, 5% Can be set in pixels, percentages, or ems

Example: Using Flexbox for Responsive Layout

{ "flexDirection": "column", "alignItems": "center", "justifyContent": "space-between" }

Example: Setting Max Width for Responsive Images

{ "maxWidth": "100%", "height": "auto" }
Note: When using Expo Web, ensure that all layout properties are compatible with both React Native and web rendering engines.

9. Optimizing Web Bundle

Example: Tree-shaking configuration

{ "expo": { "web": { "bundling": { "treeShake": true } } } }
Option Values Description
bundling.treeShake true | false Enables or disables tree-shaking to reduce bundle size. NEW
bundling.minify true | false Enables or disables minification of the web bundle. NEW
Note: Tree-shaking is enabled by default in Expo Web projects.

Example: Using Webpack config for optimization

module.exports = { optimization: { usedExports: true } };

Optimization Tips

  • Use expo install to ensure only necessary packages are included.
  • Enable treeShake in your app.json.
  • Use process.env.NODE_ENV to conditionally include debug code.

10. Deploying to Hosting

Platform Deployment Method Notes
Vercel expo export --platform web followed by vercel Supports automatic deployment via Vercel CLI. Requires vercel.json configuration.
Netlify expo export --platform web followed by netlify deploy Supports static site deployment. Requires netlify.toml or configuration in UI.
Firebase Hosting expo export --platform web followed by firebase deploy Requires Firebase CLI. Supports custom domains and SSL.
AWS Amplify expo export --platform web followed by amplify publish Supports continuous deployment from Git. Requires amplify.yml.
GitHub Pages expo export --platform web followed by gh-pages Requires gh-pages package. Supports custom domains via CNAME.

Example: Deploying to Vercel

expo export --platform web
cd dist
vercel
Note: Ensure that your expo.config.js includes the correct web configuration before exporting.
Warning: Vercel's automatic deployment may not work with all Expo configurations. Verify that assets and routing are handled correctly.

11. Using Web-Only Components

Expo provides web-specific components and APIs that are not available in native mobile environments. These components are optimized for web browsers and can be used to enhance the web experience of your Expo project.

Component Description Usage
WebImage Displays images in a web browser with optimized loading and caching.
<WebImage
  source={{ uri: 'https://example.com/image.jpg' }}
  style={{ width: 200, height: 200 }}
/>
WebVideo Displays videos in a web browser with support for various formats and controls.
<WebVideo
  source={{ uri: 'https://example.com/video.mp4' }}
  style={{ width: 300, height: 200 }}
  controls
/>
WebWebView Embeds a web view in your Expo project to display web content.
<WebWebView
  source={{ uri: 'https://example.com' }}
  style={{ width: 300, height: 300 }}
/>
Note: These components are only available when running your Expo project in a web browser. They will not function on native mobile devices.

12. Handling Browser APIs

API Description Availability Notes
document Provides access to the DOM Browser Expo does not provide a DOM. Use expo-web or react-native-web for DOM access.
window Represents the browser window Browser Expo does not provide a window object. Use expo-web or react-native-web for window access.
navigator Provides information about the browser Browser Expo does not provide a navigator object. Use expo-web or react-native-web for navigator access.
localStorage Stores data in the browser Browser Expo does not provide localStorage. Use expo-web or react-native-web for localStorage access.
fetch Fetches data from a server Browser Expo does not provide fetch. Use expo-web or react-native-web for fetch access.

Example: Using fetch in a Web Environment

import &#x27;expo-web&#x27;;

const fetchData = async () => {
  const response = await fetch(&#x27;https://api.example.com/data&#x27;);
  const data = await response.json();
  console.log(data);
};

fetchData();
Note: When using Expo with web support, you must ensure that the browser APIs are properly polyfilled or wrapped to avoid runtime errors.

Was this article helpful?