Use Expo Web with the AWS Amplify Console
Tags: aws, expo, reactnative
Published: 2019-05-20 14:54:52

---
title: Use Expo Web with the AWS Amplify Console
published: true
description: How to set up Expo and the Amplify console do automate web builds.
tags: aws, expo, react-native
cover_image: https://thepracticaldev.s3.amazonaws.com/i/b4bcdggdyppz3ck0jmmb.jpg
---

_[Cover image by Phil Roeder on Flickr](https://www.flickr.com/photos/tabor-roeder/)_

_UPDATE 02.06.2019: Expo v33 pre-view came out! Now Web builds work alongside Android and iOS builds, so I updated this post._

I'm currently working on my next video course called **MVPs with AWS**. It's about building **M**inimal **V**iable Software **P**roducts with AWS technology with a focus on **serviceful serverless** approaches.

I did customer interviews for that course; they revealed that people want to build cross-platform apps right at the start, so the front-end tech I choose was Expo. Expo lets us build Android and iOS apps with the JavaScript and React skills we already have from the web. In the v33 release, they also allow building PWAs with the help of [react-native-web](https://github.com/necolas/react-native-web). This **universal app** approach allows having one front-end code-base for three platforms.

Customers also care about continuous delivery and tooling that eases the interaction with AWS, so I choose AWS Amplify with its SDK, CLI, and Console. Amplify offers a JavaScript SDK which integrates nicely with Expo and the CLI helps to build serverless backends without the need to get too deep into CloudFormation right from the start. With the Amplify Console, we can automate the deployment of backend and frontend on every push to our repository.

**If you want to get updates to this project [just follow me on Twitter](https://twitter.com/K4y1s)**

## What

We will set up an Expo project configured for Android, iOS and Web builds with an Amplify controlled backend.

We need the following tools:

### [AWS Cloud9](https://aws.amazon.com/cloud9/)

A cloud-based IDE that can be accessed via a browser. It comes with Node.js, npm and the AWS SDK pre-installed. We could install these tools manually on our own if we want to use another editor.

### [GitHub Repository](https://github.com/)

The continuous delivery is triggered by Git commits, so we need a repository the Amplify Console can _watch_.

### [Expo](https://expo.io/)

We use the Expo CLI to init a project and build an Android, iOS and Web client from it later. 

### [AWS Amplify](https://aws-amplify.github.io)

We will use the Amplify CLI and Console. The CLI is used to add Amplify features to our Expo project, and the Console is used to watch our Git repository for commits that will trigger builds and deploys.

## How

> **Prerequisites**
> An AWS account and a Cloud9 environment. This is pretty straight forward to set up, but people who struggle with it [can look at the first five steps of this article](https://dev.to/kayis/10-easy-steps-to-create-aws-lambda-functions-with-the-serverless-framework--reason-in-aws-cloud9-8d1).
> A GitHub account.

The setup will consist of seven steps:

1. Create an Expo Account and Login
2. Initialize Expo Project
3. Add Script and Dependencies
4. Initialize Amplify Project
5. Commit Amplify files to Git
6. Set up and push changes GitHub Repository
7. Set up and run Amplify Console Build

## 1. Create an Expo Account and Login

First, step is to create an Expo account, so our published Android and iOS projects will be automatically available on the Expo-Client.

### Account Creation

An Expo account is totally free and can be created [here](https://expo.io/signup).

### Download and Login with Expo Client

We need to install the Expo client for the mobile platform of our choosing. The Android client can be found in the [Play Store](https://play.google.com/store/apps/details?id=host.exp.exponent)

After the install, we need to log in with our freshly created Expo account. This will make projects we published with the Expo-CLI available in the client automatically.

### Login with the Expo-CLI

To log in with the Expo-CLI, we just need to run the login command, this will create some files in our `~/.expo` that keeps track of our login state.

    npx expo-cli login -u <USERNAME> -p <PASSWORD>

## 2. Initialize Expo Project

Next, we create a new project with the help of the Expo CLI tool.

    npx expo-cli init universal-app --template blank@next

We give the project the name "Universal App".

## 3. Add Scripts and Dependencies

We need to install the `expo-cli` package as `devDependency`. Installing global dependencies locally in the `package.json` makes them available _as if they were global_ inside the npm scripts.

    cd universal-app
    npm i -D expo-cli

At the moment of writing, Expo projects come without a build or publish script; we need to add this to our `package.json`.

Adding a `build` script to the `package.json`s `scripts` section:

```json
{
...
  "scripts": {
    "login": "expo login -u $EXPO_USERNAME -p $EXPO_PASSWORD",
    "build": "expo build:web",
    "publish": "expo publish --non-interactive",
    ...
  },
...
}
```

The build script is needed for the web build, so Amplify Console can build and deploy it to AWS.

The publish script is needed for the Android and iOS build, so Expo will build and publish to the Expo clients on these platforms.

Since it uses the Expo infrastructure, it needs username and password.

We use environment variables for this, so the Expo credentials don't show up in the logs.

## 4. Initialize Amplify Project

Next, we have to add Amplify support to our project. Cloud9 uses a different file-name to store AWS credentials than the Amplify CLI expects, so we have to create a symlink before we can initialize the project.

    ln -s ~/.aws/credentials ~/.aws/config
    npx @aws-amplify/cli init

This will ask us a few questions. We choose these answers:

> ? Enter a name for the project **universal-app**
> ? Enter a name for the environment **dev**
> ? Choose your default editor: **None**
> ? Choose the type of app that you're building **javascript**
> Please tell us about your project
> ? What javascript framework are you using **react-native**
> ? Source Directory Path: **/**
> ? Distribution Directory Path: **/web-build**
> ? Build Command: **npm run-script build**
> ? Start Command: **npm run-script start**
> Using default provider **awscloudformation**
> ? Do you want to use an AWS profile? **Yes**
> ? Please choose the profile you want to use **default**

This will create a basic Amplify backend infrastructure in the cloud; IAM roles, S3 buckets for the deployment of generated CloudFormation templates, etc.

## 5. Commit Amplify files to Git

The Amplify Console will build our project when we push any changes to a remote Git repository, so we need to get our changes into Git before we move on.

Then we can add all our new files and do an initial commit:

    git add -A
    git commit -m "Init"

## 6. Set up and push changes to GitHub Repository

A new GitHub repository can be set up [here.](https://github.com/new) Let's call it like our project **universal-app**. To keep it simple, we create a **public** repository.

We also need to set up SSH authentication for our Cloud9 machine on Github.

A key-pair can be generated with:

    ssh-keygen

We can look it up at our Cloud9 machine with:

    tail /home/ec2-user/.ssh/id_rsa.pub

The public key needs to be given a title and pasted [here](https://github.com/settings/ssh/new).

    
After the creation, we can push our local changes:

    git remote add origin git@github.com:<GITHUB_USERNAME>/expo-web-app.git
    git push -u origin master

## 7. Set up and run Amplify Console Build

Now that we have our project created, configured and up on GitHub, we can set up the Amplify Console to do our build.

To connect we need to go [here](https://eu-west-1.console.aws.amazon.com/amplify/home?region=eu-west-1#/create).

I use `eu-west-1` here, but you can use whatever region you like.

Choose GitHub as a provider and the `universal-app` repository we created, with branch `master`.

In the following form, we get asked a few things for the setup.

> Would you like Amplify Console to deploy changes to these resources with your frontend?

Yes, we want. Let's choose the `dev` environment we created with the Amplify CLI. This is necessary if we wanted to add other Amplify features.

> Select an existing service role or create a new one so Amplify Console may access your resources.

We need to create a new IAM role for this, but the process is done via a wizard. Only clicking **Next** until finished. Then we go back to the form, refresh the roles and add our newly created `amplifyconsole-backend-role`

The build settings need to be edited. They were created automatically, but need to be tweaked a bit for Expo Web builds.

```yaml
version: 0.1
backend:
  phases:
    build:
      commands:
        - amplifyPush --simple
frontend:
  phases:
    preBuild:
      commands:
        - echo fs.inotify.max_user_watches=524288 | tee -a /etc/sysctl.conf && sysctl -p
        - npm ci
        - npm run login &
        - sleep 2s
    build:
      commands:
        - npm run publish --non-interactive
        - npm run build
  artifacts:
    baseDirectory: web-build
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
      - $(npm root --global)/**/*
```

1. Increase the file watchers for the system, otherwise `expo publish` will fail later.
2. `npm ci` runs so all dependencies (including `expo-cli`) are installed.
3. Run the login script but don't wait for it to finish (&), otherwise the build will freeze.
4. Sleep two seconds, so the login script has some time to do its thing.
5. Build and publish the Android and iOS versions to the Expo Client
6. Build the Web version to Amplify  

We also need to set up the *Environment Variables* for the Expo CLI login. We have to add variables named `EXPO_USERNAME` and `EXPO_PASSWORD` here filled with the corresponding values we used when we created an Expo account.

After this, we can click on **Next** and then **Save and Deploy**.

## Bonus: Push a Change to Trigger Build

Now that everything is up and running, we can change a file and push it to our remote repository at GitHub and watch the Amplify Console magic happen.

Let's change the text in our `App.js`

```javascript
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default class App extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text>Awesome universal Expo app backed by AWS Amplify!</Text>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});
```

Add the changes, commit, and push it.

    git add -A
    git commit -m "Change text"
    git push

We can watch the builds [here](https://eu-west-1.console.aws.amazon.com/amplify/home?region=eu-west-1#/).

## Conclusion

When Expo version 33 is released we will be able to leverage Expo on iOS, Android and the Web with one code-base without sacrificing the power of native UI widgets.

Amplify accelerates this development even more by easing the pain of managing AWS services and leveraging the full force of serviceful serverless computing and providing one back-end for Android, iOS and Web clients.

I believe this stack to become a solid foundation to build apps for years to go.

---

Here is the [project code](https://github.com/kay-is/universal-app)