Using React with Cordova

Shubham Patil
6 min readAug 12, 2019

--

Designed by starline / Freepik

In this article I’ll be providing an overview of how you can use react js with cordova to build a hybrid mobile app.

Overview

Before getting into the details, let’s go over some basic information regarding the frameworks

Cordova

Apache cordova is a mobile application development framework which can be used to build hybrid (cross platform) mobile apps using web technologies like HTML, Javascript. A single code base can be built to run on different platforms like android, ios and windows.

React

React is a javascript library used for building user interfaces and has been gaining popularity. It allows you to build reusable and stateful components.

So let’s get started! I’m assuming that node, npm and cordova is already installed.

  1. Let’s start by creating a cordova project. Open your terminal and move around to a location of your choice and execute the below command:
$ cordova create cordovaReactProject

This command creates a folder cordovaReactProject containing the cordova project.

2. Let’s set up a react project using create-react-app simultaneously. create-react-app is super easy to use, one command takes care of all the webpack, babel configurations to help you get started.

If you are using npm v5.2 + it comes installed with npx so you can directly use:

$ npx create-react-app reactproject

For npm 5.1 and earlier, create-react-app needs to be installed globally first:

$ npm install -g create-react-app
$ create-react-app reactproject

This creates a folder reactproject which contains the react project code base.

To make sure the react project has setup correctly you can try running npm start within the project directory:

$ cd reactproject
$ npm start

This should start a server and on opening the server url ( http://localhost:3000 ) in the browser you should see something like this:

To summarize we’ve created two seperate project folders cordova and react:

  • cordovaReactProject -> folder containing cordova project
  • reactproject -> folder containing react project

3. The react project would have a directory structure similar to:

├── .gitignore
├── package.json
├── package-lock.json
├── node_modules
│ ├──..
│ ├──..
│ .
│ .
│ └──
├── public
│ ├── favicon.ico
│ ├── index.html ----> page template
│ └── manifest.json
├── README.md
└── src ----> source files , development directory
├── App.css
├── App.js
├── App.test.js
├── index.css
├── index.js ----> starting point
├── logo.svg
└── serviceWorker.js

The package.json file would look something like this:

Now we need to merge the two projects (Important):

  • Copy the src/ and public/ directories from reactproject folder to cordovaReactProject folder
  • The package.json files also need to be merged. Copy the “scripts”, “dependencies” and “browserList” keys from reactproject/package.json to cordovaReactProject/package.json. Eventually cordovaReactProject/package.json should look like:
cordovaReactProject updated package.json

4. Now that we have merged our react project into our cordova project the latter would have the following directory structure with src/ being our main development directory:

├── config.xml
├── hooks
│ └── README.md
├── package.json --> (merged from the react project)
├── platforms
├── plugins
├── public ---> (copied from the react project)
│ ├── favicon.ico
│ ├── index.html
│ └── manifest.json
├── src --> Main working directory (copied from the react project)
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── index.css
│ ├── index.js
│ ├── logo.svg
│ └── serviceWorker.js
└── www -------> Build directory
├── css
│ └── index.css
├── img
│ └── logo.png
├── index.html
└── js
└── index.js

Since package.json was manually updated we need to make sure that the dependencies are installed:

$ cd cordovaReactProject/
$ npm install

To make sure everything has been configured correctly, you can try running npm start in the project directory. The server should start and a page resembling the one posted earlier should appear in your browser on the server url.

5. Now, we need to take care of certain important things:

  • Updating the meta tags in our main template page:

Add the following <meta> tags in the <head> of public/index.html.

<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;"><meta name="format-detection" content="telephone=no"><meta name="msapplication-tap-highlight" content="no"><meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
  • Loading cordova.js in our main template page:

Add the following script tag just before </body> in public/index.html

<script src="cordova.js" type="text/javascript"></script>
  • Configuring react dom to be loaded after cordova’s ondevice ready event:

Since scr/index.js file is the entry point we need to tweak it a bit so that the react dom loads after the “deviceready” event has been fired by cordova.

  • Updating “homepage” in package.json:

The index.html file within the build folder has absolute paths for loading the assets (js, css files). Since the HTML file is going to run directly in webview rather than being hosted on a server the assets need to be accessed using a relative path. For e.g. we want

<script src=”./foo/bar.js”></script>

instead of

<script src="/foo/bar.js></script>

The solution for this is to add a “homepage” property in package.json as metioned below. Adding this would make sure that the assets are fetched using a relative path in the index.html file.

"homepage": "./"

6. The code from the src/ directory written in JSX and ES6 cannot be directly used as it is inside the cordova app. So basically the production build of our react app needs to be used to build the cordova app.

Designed by starline / Freepik

We can easily automate this process using cordova hooks ( more info ). Since we need to execute the react build command before cordova build is prepared, we can use the before_prepare cordova hook.

Hooks need to be defined in the project’s config.xml file. Add the below entry under <widget>:

<hook type="before_prepare" src="scripts/prebuild.js" />

This would execute the scripts/prebuild.js before a cordova build starts. Our prebuild.js file would contain a mechanism to execute the react build.

The advantage of configuring a hook is that you don’t need to worry about platform specific constructs in configuring your tasks e.g. rm -rf, cp won’t work on windows, a folder is accessed as /foo/bar in linux and C:\\foo\\bar in windows.

7. Now that the hook is defined, create a scripts folder within the project directory i.e. cordovaReactProject/ in this case. Within the scripts folder create a prebuild.js file as well.

In this file we need to perform two main functions:

  • Execute the react build process
  • React-scripts generates the build output to the build/ folder and cordova uses www/ as its input directory. So once the react build is completed we need to rename build/ to www/

I’ve used an additional rimraf module in my cordova hook, to install that:

$ cd cordovaReactProject
$ npm i rimraf --save

My prebuild.js file:

8. All done! Now we’ll build the cordova app for android to see if everything works!

Within the cordova project execute ( Android sdk and build tools must be installed — Details ):

$ cordova platform add android
$ cordova run android

This would first execute the cordova hook written, then build an apk and run it on an emulator or an android device if connected via usb.

Cordova app android build running on my android phone

Some other tips

  • If you are planning to use react-router-dom for routing in the app, use <HashRouter> instead of <BrowserRouter>
  • While accessing the cordova object access it using the window object, or else the react build would throw an undefined variable exception. For .e.g if you are using the local notification plugin ( plugin link ), instead of using it as:
cordova.plugins.notification.local.schedule({
....
});

access it using the window object:

window.cordova.plugins.notification.local.schedule({
....
});

There are other approaches of setting up a project with this configuration, I’ve used this particular approach as seting up a react project from scratch can be a challenging task.

It involves installing npm modules, creating configurations amongst other things. Doing all of this inside a cordova project adds some complexity. Using create-react-app solves a lot of these problems.

The source code is available in this github repository — https://github.com/pshubham95/cordova-react-example . You can clone this repository directly to get started.

That’s all folks! Happy coding 🍻

--

--