<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Craft Delivery</title>
    <description>The latest articles on DEV Community by Craft Delivery (@craftdelivery).</description>
    <link>https://dev.to/craftdelivery</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F174606%2F82bca7ce-8182-4236-8bfe-9bf02cab10fe.png</url>
      <title>DEV Community: Craft Delivery</title>
      <link>https://dev.to/craftdelivery</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/craftdelivery"/>
    <language>en</language>
    <item>
      <title>Expo.js apps using a localhost backend over ngrok</title>
      <dc:creator>Craft Delivery</dc:creator>
      <pubDate>Sun, 17 Jan 2021 18:26:53 +0000</pubDate>
      <link>https://dev.to/craftdelivery/expo-js-apps-using-a-localhost-backend-over-ngrok-hb6</link>
      <guid>https://dev.to/craftdelivery/expo-js-apps-using-a-localhost-backend-over-ngrok-hb6</guid>
      <description>&lt;p&gt;The issue arises when creating React Native apps using Expo.js where you wish to have a local backend instead of a live url. Ngrok is used by many to accomplish this, however, if you are using a free account it can take some repeated effort to keep everything working&lt;/p&gt;

&lt;p&gt;Free Ngrok urls are only available for 90 minutes, after which you need to restart it and get a fresh url&lt;/p&gt;

&lt;p&gt;We can automate the process to make it as painless as possible&lt;/p&gt;

&lt;p&gt;All files mentioned should be created in the project root beside &lt;code&gt;package.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Ensure axios and expo-constants are installed: &lt;code&gt;expo add axios expo-constants&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We will assume your local api is running on port 3333&lt;/p&gt;

&lt;p&gt;First create a script called &lt;code&gt;local&lt;/code&gt; in &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "scripts": {
    "start": "expo start",
    "local": "node ngrokhandler.js &amp;amp;&amp;amp; EXPO_NGROK=1 expo start",
    ...
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pass &lt;code&gt;EXPO_NGROK=1&lt;/code&gt; to &lt;code&gt;expo start&lt;/code&gt; that way &lt;code&gt;app.config.js&lt;/code&gt; can choose to load ngrok or just ingore it&lt;/p&gt;

&lt;p&gt;Once you've added all the pieces, start the app locally using &lt;code&gt;yarn run local&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;create a file &lt;code&gt;ngrokhandler.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Note: if this is your only tunnel, then the local ngrok server is on port 4040, if you have more than one this number increments, so note it when you start ngrok. If you see a number greater than 4040, you may have ngrok running elsewhere&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require('fs')
const axios = require('axios')

// ngrok starts at port 4040
// subsequent tunnels are numbered 4040 + n
axios.get('http://127.0.0.1:4040/api/tunnels')
.then(resp =&amp;gt; {
  const httpsTunnel = resp.data.tunnels.find(t =&amp;gt; t.proto==='https')
  const url = httpsTunnel.public_url
  fs.writeFileSync('./NGROK_URL', url)
})
.catch(e =&amp;gt; {
  console.log('START NGROK in another window: ngrok http 3333')
  // exit err code so &amp;amp;&amp;amp; in package json does not execute the expo start command
  process.exit(2)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This writes the current https tunnel url to a text file called &lt;code&gt;NGROK_URL&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Create or modify &lt;code&gt;app.config.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const fs = require('fs')

// on production ngrokUrl will be null
// you don't need to have the file NGROK_URL
// in production

let ngrokUrl = null
if (process.env.EXPO_NGROK === '1') {
  ngrokUrl = fs.readFileSync('./NGROK_URL', { encoding: 'utf8'})
}

export default ({ config }) =&amp;gt; {
  return {
    ...config,
    extra: {
      ...config.extra,
      ngrokUrl,
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brings in your &lt;code&gt;app.json&lt;/code&gt; via the config param and adds the ngrok url to the extra object. Put anything else you want to add in extra&lt;/p&gt;

&lt;p&gt;You can then access this via &lt;code&gt;expo-constants&lt;/code&gt;. You probably don't want to use an ngrok url in production so we can turn it off by applying the &lt;code&gt;__DEV__&lt;/code&gt; variable expo provides:&lt;/p&gt;

&lt;p&gt;Example: &lt;code&gt;api.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import Constants from 'expo-constants'
const { ngrokUrl } = Constants.manifest.extra

const isLocal = ngrokUrl &amp;amp;&amp;amp; __DEV__

const productionUrl = 'https://example.com'

const baseUrl = isLocal ? ngrokUrl : productionUrl

// now we can export an object of api endpoints
export default {
  login: `${baseUrl}/login`,
  etc: ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get your api running on port 3333.&lt;/p&gt;

&lt;p&gt;Open another terminal and enter &lt;code&gt;ngrok http 3333&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now you can run the app using &lt;code&gt;yarn run local&lt;/code&gt; and the local url will be automatically added to the app. You have 90 minutes before you'll need to break the expo app and ngrok and re-run the commands (ctrl-c, up and enter in each terminal window)&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
