Skip to content

Commit 5b17b8c

Browse files
authored
Merge pull request #15 from combine/feature/cordova
Add support for Cordova + hot reloading
2 parents 322806a + 6b593e8 commit 5b17b8c

24 files changed

+471
-68
lines changed

.eslintrc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
"node": true
3131
},
3232
"globals": {
33+
'__CORDOVA__': true,
34+
'__BASE_URL__': true,
3335
expect: true
3436
},
3537
"extends": "eslint:recommended",

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,13 @@ npm-debug.log*
55
# ignore built static files
66
dist/
77
webpack-assets.json
8+
9+
# cordova ignores
10+
cordova/www/*
11+
cordova/www/**.*
12+
!cordova/www/.gitkeep
13+
cordova/plugins/
14+
cordova/platforms/
15+
16+
# cordova build and release configurations
17+
scripts/cordova/config/*.json

README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,20 @@ npm run test:all
105105

106106
This will run all files that are suffixed with a `.test.js`.
107107

108-
## Deploying to Heroku
108+
## Changing the Asset Host
109109

110-
Just set an environment variable to point the asset host to whereever you want,
111-
since it defaults to `localhost:3001`. If using Heroku to store assets, just use
112-
a local route. Otherwise, set it to the CDN of your choice.
110+
In production scenarios, you may want your assets to be hosted elsewhere besides
111+
on your server. Just set an environment variable to point the asset host to
112+
where ever you want, as defaults to `localhost:3001`. Just set it to the CDN of
113+
your choice.
114+
115+
If you're using Heroku:
113116
```
114117
heroku config:set ASSET_HOST=/dist/
115118
# OR
116119
heroku config:set ASSET_HOST=https://s3.amazonaws.com/mybucket/myasssets/
117120
```
121+
122+
## Building Cordova Apps
123+
124+
Please see [Building Cordova Apps](docs/cordova.md)

client/index.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Provider } from 'react-redux';
55
import { Router } from 'react-router';
66
import { routes } from 'routes';
77
import configureStore from 'config/store';
8-
import { browserHistory } from 'react-router';
8+
import { browserHistory, hashHistory } from 'react-router';
99
import { syncHistoryWithStore } from 'react-router-redux';
1010

1111
/* Images
@@ -28,7 +28,10 @@ const rootElement = document.getElementById('app');
2828
// rendering.
2929
const initialState = window.__INITIAL_STATE__;
3030
const store = configureStore(initialState);
31-
const history = syncHistoryWithStore(browserHistory, store);
31+
const history = syncHistoryWithStore(
32+
(__CORDOVA__ ? hashHistory : browserHistory),
33+
store
34+
);
3235

3336
// Render the app!
3437
ReactDOM.render(

common/layouts/cordova.html

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!doctype html>
2+
<html>
3+
<head>
4+
<title><%= htmlWebpackPlugin.options.title %></title>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width height=device-height" />
7+
<!-- Cordova app security policy:
8+
* gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
9+
* https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
10+
* Disables use of eval() and inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
11+
* Enable inline JS: add 'unsafe-inline' to default-src
12+
* Enable eval(): add 'unsafe-eval' to default-src
13+
-->
14+
<meta http-equiv="Content-Security-Policy" content="default-src * data: gap: https://ssl.gstatic.com; style-src * 'unsafe-inline'; script-src * 'unsafe-inline' 'unsafe-eval'">
15+
<meta name="apple-mobile-web-app-capable" content="yes">
16+
<link type="text/css" rel="stylesheet" href="<%= htmlWebpackPlugin.options.stylesheet %>" />
17+
</head>
18+
<body>
19+
<div id="app"></div>
20+
<script>window.__INITIAL_STATE__ = {};</script>
21+
<script src="cordova.js"></script>
22+
<script src="<%= htmlWebpackPlugin.options.bundleJs %>"></script>
23+
</body>
24+
</html>

docs/cordova.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Building Cordova Apps
2+
3+
First, make sure you have Cordova installed:
4+
5+
```
6+
npm install -g cordova
7+
```
8+
9+
In your project directory, initialize the Cordova app:
10+
11+
```
12+
cordova create ./cordova/ com.org.appname "My App"
13+
```
14+
15+
Add the platform(s) you want to build for:
16+
17+
```
18+
cd cordova/
19+
cordova platform add ios # or 'android'
20+
```
21+
22+
Install plugins (if you don't have a `/plugins` folder)
23+
```
24+
cordova prepare
25+
```
26+
27+
## Build/Start Dev Environment
28+
29+
```
30+
npm run cordova:dev:start # build for development with hot reloading
31+
npm run cordova:dev:build # build for development without hot reloading
32+
33+
npm run cordova:prod:build # build for production without hot reloading
34+
```
35+
36+
## Start a simulator/emulator
37+
38+
* iOS - CLI
39+
40+
Install XCode, then:
41+
42+
```
43+
npm install -g ios-deploy
44+
cd cordova && cordova run ios
45+
```
46+
47+
* iOS - XCode
48+
49+
Open the file located in `./cordova/platforms/ios/AppName.xcodeproj`.
50+
51+
* Android - CLI
52+
53+
Install the Android SDK, then:
54+
```
55+
cd cordova && cordova run android
56+
```
57+
58+
## Committing to Source Control
59+
The `cordova/` directory is not .gitignored, but several directories are, as
60+
they are directories containing built files. You'll need to leave the main
61+
`cordova/` directory in source control as it will contain configuration files
62+
that you will need for your app.
63+
64+
## Distributing Betas
65+
66+
You may want to distribute the app via Fabric (Crashlytics). To do so, prepare
67+
the following files (copy and rename them):
68+
69+
```
70+
build/fabric.json.example -> build/fabric.json
71+
build/config/release.json.example -> build/config/release.json
72+
```
73+
74+
Fill in the fields in the JSON files properly, then run the following commands:
75+
76+
```
77+
npm run cordova:build:prod # build the source files for cordova's www
78+
npm run cordova:dist # build and distribute the binary to Fabric/Crashlytics for all platforms
79+
80+
# OR
81+
npm run cordova:dist:android # distribute android to Fabric
82+
npm run cordova:dist:ios # distribute ios to Fabric
83+
```
84+
85+
## Additional Notes
86+
87+
If you're debugging in a mobile browser and you want to access your project
88+
locally, do the following:
89+
90+
- Make sure your mobile device on the same network as your desktop/laptop.
91+
- Run `npm start` with a `HOSTNAME` environment variable set to your computer's
92+
local ip address (the computer that your dev environment is on):
93+
```
94+
HOSTNAME=10.0.1.3 npm start
95+
```
96+
- Browse to `http://10.0.1.3:3000` on your mobile device.

package.json

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,35 @@
1313
"npm": "3.x.x"
1414
},
1515
"scripts": {
16-
"start": "npm run build:development && npm run start:development",
17-
"start:production": "NODE_ENV=production node server",
18-
"start:development": "NODE_ENV=development npm run start:development:client & npm run start:development:server",
19-
"start:development:client": "node webpack/config.development.hot",
20-
"start:development:server": "$(npm bin)/nodemon server",
21-
"build:development": "$(npm bin)/webpack --progress --colors --display-error-details --config webpack/config.development.js",
22-
"build:production": "NODE_ENV=production $(npm bin)/webpack -p --optimize-dedupe --config webpack/config.production.js",
16+
"start": "npm run dev:build && npm run dev:start",
17+
"dev:start": "npm run dev:start:client & npm run dev:start:server",
18+
"dev:start:cordova": "npm run cordova:dev:build:hot; npm run dev:start:server & npm run dev:start:cordova:client",
19+
"dev:start:cordova:client": "NODE_ENV=development node webpack/config.dev.cordova.hot",
20+
"dev:start:server": "NODE_ENV=development $(npm bin)/nodemon server",
21+
"dev:start:client": "NODE_ENV=development node webpack/config.dev.hot",
22+
"dev:build": "NODE_ENV=development $(npm bin)/webpack --progress --colors --display-error-details --config webpack/config.dev.js",
23+
"prod:build": "NODE_ENV=production $(npm bin)/webpack -p --optimize-dedupe --config webpack/config.prod.js",
24+
"prod:start": "NODE_ENV=production pm2 start server --name='callai'",
25+
"cordova:dev:build:hot": "NODE_ENV=development npm run cordova:clean; HOT=true $(npm bin)/webpack --progress --colors --display-error-details --config webpack/config.dev.cordova.js; npm run cordova:prepare",
26+
"cordova:dev:build": "NODE_ENV=development npm run cordova:clean; $(npm bin)/webpack --progress --colors --display-error-details --config webpack/config.dev.cordova.js; npm run cordova:prepare",
27+
"cordova:prod:build": "NODE_ENV=production npm run cordova:clean; NODE_ENV=production $(npm bin)/webpack -p --optimize-dedupe --config webpack/config.prod.cordova.js; npm run cordova:prepare;",
28+
"cordova:dist": "npm run cordova:dist:android && npm run cordova:dist:ios",
29+
"cordova:dist:android": "node ./scripts/cordova --platform android --config release --distribute",
30+
"crodova:dist:ios": "node ./scripts/cordova --platform ios --config release --distribute",
31+
"cordova:clean": "rm -f $(find cordova/www/* 2>/dev/null -type f | grep -v 'gitkeep')",
32+
"cordova:prepare": "cd cordova && cordova prepare",
2333
"test": "$(npm bin)/mocha --recursive --compilers js:babel-register",
2434
"test:all": "$(npm bin)/mocha --recursive --compilers js:babel-register $(find . -path ./node_modules -prune -o -name '*.test.js' -print)",
2535
"test:watch": "npm test -- --watch",
2636
"test:all:watch": "$(npm bin)/mocha --recursive --compilers js:babel-register $(find . -path ./node_modules -prune -o -name '*.test.js' -print) --watch",
2737
"lint": "$(npm bin)/eslint --ignore-pattern **/node_modules/* --ext .js,.jsx .",
28-
"postinstall": "if [ \"$NODE_ENV\" = \"production\" ]; then npm run build:production; fi"
38+
"postinstall": "if [ \"$NODE_ENV\" = \"production\" ]; then npm run prod:build; fi"
2939
},
3040
"devDependencies": {
3141
"babel-eslint": "6.0.4",
3242
"chai": "3.5.0",
3343
"chai-immutable": "1.5.4",
44+
"cordova-lib": "6.2.0",
3445
"eslint": "2.12.0",
3546
"eslint-plugin-react": "5.1.1",
3647
"mocha": "2.5.3",

scripts/cordova/build.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
const fs = require('fs');
2+
const cordova = require('cordova-lib').cordova;
3+
const fabric = require('./fabric');
4+
5+
/**
6+
* cordovaBuild()
7+
* @param options.platforms [String] Comma-delimited platforms, e.g. 'ios,android'
8+
* @param options.config [String] The build configuration: 'debug', 'release', or other defined.
9+
* @param options.target [String] (iOS only) The target platform: 'device' or 'emulator'
10+
* @param options.distribute [Boolean] Deploy to Crashlytics.
11+
* NOTE: To build signed APKs for Android, cordova/build.json must be properly updated.
12+
*/
13+
const cordovaBuild = (options) => {
14+
const opts = arguments.length >= 1 ? options : {};
15+
const { platforms = 'ios,android', config = 'release', target = 'device', distribute } = opts;
16+
const configFile = `${__dirname}/config/${config}.json`;
17+
const buildOpts = {
18+
platforms: platforms.split(','),
19+
options: [`--${target}`, `--${config}`, `--buildConfig=${configFile}`]
20+
};
21+
22+
// Check if config file exists, if not warn the user.
23+
if (config) {
24+
try {
25+
fs.accessSync(configFile, fs.F_OK);
26+
} catch (e) {
27+
console.log('Warning: build file not found, using defaults...');
28+
}
29+
}
30+
31+
// switch to cordova directory
32+
process.chdir('./cordova');
33+
34+
// build with options and distribute to Fabric if specified
35+
return cordova.raw.build(buildOpts).then(
36+
function() {
37+
if (distribute) {
38+
fabric.distribute(platforms, target);
39+
}
40+
},
41+
function(error) {
42+
console.log('Build failed:', error);
43+
}
44+
);
45+
};
46+
47+
module.exports = cordovaBuild;
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"apiKey": "my-api-key",
3+
"apiSecret": "my-build-secret"
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"android": {
3+
"release": {
4+
"keystore": "path/to/keystore.jks",
5+
"storePassword": "myStorePassword",
6+
"alias": "myKeyAlias",
7+
"password" : "myKeyPassword",
8+
"keystoreType": "jks"
9+
}
10+
}
11+
}

0 commit comments

Comments
 (0)