1 | # Re-Natal
|
2 | ### A utility for building ClojureScript-based React Native apps
|
3 | Artur Girenko
|
4 | [@drapanjanas](https://twitter.com/drapanjanas)
|
5 |
|
6 | ---
|
7 |
|
8 | Re-Natal is a simple command-line utility that automates most of the process of
|
9 | setting up a React Native app running on ClojureScript with [Reagent] + [re-frame](https://github.com/Day8/re-frame), [Om.Next] or [Rum].
|
10 |
|
11 | This project is a fork of [dmotz/natal](https://github.com/dmotz/natal) by Dan Motzenbecker.
|
12 |
|
13 | Figwheel support is based on the brilliant solution developed by Will Decker [decker405/figwheel-react-native](https://github.com/decker405/figwheel-react-native),
|
14 | which works on both platforms.
|
15 |
|
16 |
|
17 | For more ClojureScript React Native resources visit [cljsrn.org](http://cljsrn.org).
|
18 |
|
19 | Contributions are very welcome.
|
20 |
|
21 | ## Status
|
22 | - Uses [React Native] v0.48.4
|
23 | - Reusable codebase between iOS and Android
|
24 | - Figwheel used for REPL and live coding
|
25 | - Works in iOS (real device and simulator)
|
26 | - Works in Android (real device and simulators, specifically AVD and Genymotion)
|
27 | - Figwheel REPL can be started from within nREPL
|
28 | - Simultaneous development of iOS and Android apps
|
29 | - Manual reload and automatic hot reload
|
30 | - Custom react-native components supported
|
31 | - Source maps available
|
32 | - Supported React wrappers:
|
33 | [Reagent], [Om.Next], and [Rum]
|
34 | - Support of windows (UWP and WPF) apps
|
35 | - [Unified way of using static images of React Native 0.14+](https://facebook.github.io/react-native/docs/images.html) supported
|
36 |
|
37 | ## Compatibility with RN versions
|
38 | Current version of re-natal might not work correctly with older versions of React Native
|
39 | - use current version of re-natal with React Native >= v0.46
|
40 | - use re-natal < v0.5.0 with React Native < v0.46
|
41 |
|
42 | ## Dependencies
|
43 | As Re-Natal is an orchestration of many individual tools, there are quite a few dependencies.
|
44 | If you've previously done React Native or Clojure development, you should hopefully
|
45 | have most installed already. Platform dependencies are listed under their respective tools.
|
46 |
|
47 | - [npm](https://www.npmjs.com) `>=1.4`
|
48 | - [Node.js](https://nodejs.org) `>=7.1.0`
|
49 | - [react-native-cli](https://www.npmjs.com/package/react-native-cli) `>=0.1.7` (install with `npm install -g react-native-cli`)
|
50 | - [watchman](https://facebook.github.io/watchman/) `>=4.9.0`
|
51 | - [Leiningen](http://leiningen.org) `>=2.5.3`
|
52 | - [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html)
|
53 |
|
54 | For iOS development:
|
55 | - [Xcode](https://developer.apple.com/xcode) (+ Command Line Tools) `>=6.3`
|
56 | - [OS X](http://www.apple.com/osx) `>=10.10`
|
57 |
|
58 | ## Creating a new project
|
59 |
|
60 | Before getting started, make sure you have the
|
61 | [required dependencies](#dependencies) installed.
|
62 |
|
63 | Then, install the CLI using npm:
|
64 |
|
65 | ```
|
66 | $ npm install -g re-natal
|
67 | ```
|
68 |
|
69 | To generate a new app, run `re-natal init` with your app's name as an argument:
|
70 |
|
71 | ```
|
72 | $ re-natal init FutureApp
|
73 | ```
|
74 |
|
75 | This will generate a project which uses Reagent v0.6.
|
76 | You may specify the -i option to choose a specific React wrapper: Om.Next, Reagent v0.6 or Rum:
|
77 |
|
78 | ```
|
79 | $ re-natal init FutureApp -i [om-next | reagent6 | rum]
|
80 | ```
|
81 |
|
82 | If your app's name is more than a single word, be sure to type it in CamelCase.
|
83 | A corresponding hyphenated Clojure namespace will be created.
|
84 |
|
85 | The init process will take a few minutes — coffee break! If all goes well you should see basic instructions on how to run in iOS simulator.
|
86 |
|
87 | ## Development with Figwheel
|
88 |
|
89 | Initially the `index.*.js` files are generated with the production profile, ready for deployment.
|
90 | However, during development it is better to use the development profile and integrate with Figwheel. Switch to the development profile with:
|
91 |
|
92 | ```
|
93 | $ re-natal use-figwheel
|
94 | ```
|
95 |
|
96 | This command needs to be run every time you switch to the development profile or specify a development environment (with `use-ios-device` or `use-android-device`).
|
97 |
|
98 | NOTE: You might need to restart React Native Packager and reload your app.
|
99 |
|
100 | Start the Figwheel REPL with
|
101 |
|
102 | ```
|
103 | $ lein figwheel [ios | android]
|
104 | ```
|
105 |
|
106 | If all went well you should see the REPL prompt and changes in source files should be hot-loaded by Figwheel.
|
107 |
|
108 | #### Starting Figwheel REPL from nREPL
|
109 | To start Figwheel from within nREPL session:
|
110 | ```
|
111 | $ lein repl
|
112 | ```
|
113 | Then in the nREPL prompt type:
|
114 | ```
|
115 | user=> (start-figwheel "ios")
|
116 | ```
|
117 | Or, for Android build type:
|
118 | ```
|
119 | user=> (start-figwheel "android")
|
120 | ```
|
121 | Or, for both type:
|
122 | ```
|
123 | user=> (start-figwheel "ios" "android")
|
124 | ```
|
125 |
|
126 | ## Running the app
|
127 | ### Note for Linux users
|
128 | On Linux, the React Native Packager has to be started manually with
|
129 | ```
|
130 | react-native start
|
131 | ```
|
132 | See [here](#running-on-linux) for more details.
|
133 |
|
134 | ### iOS
|
135 | #### Using iOS simulator
|
136 |
|
137 | ```
|
138 | re-natal use-ios-device simulator
|
139 | react-native run-ios
|
140 | ```
|
141 |
|
142 | #### Using real iOS device
|
143 |
|
144 | ```
|
145 | re-natal use-ios-device real
|
146 | ```
|
147 |
|
148 | If this doesn't correctly detect your computer's IP you can pass your IP address explicitly: `re-natal use-ios-device <IP address>`.
|
149 | And then run
|
150 |
|
151 | ```
|
152 | react-native run-ios
|
153 | ```
|
154 |
|
155 | #### Switching between iOS devices
|
156 | Run `use-ios-device` to configure device type you want to use in development:
|
157 | ```
|
158 | $ re-natal use-ios-device <real|simulator>
|
159 | $ re-natal use-figwheel
|
160 | $ lein figwheel ios
|
161 | ```
|
162 |
|
163 | ---
|
164 |
|
165 | ### Android
|
166 |
|
167 | #### Using Android Virtual Device (AVD)
|
168 | [Set up a virtual device in AVD](https://developer.android.com/studio/run/managing-avds.html). Start the virtual device then run
|
169 | ```
|
170 | $ re-natal use-android-device avd
|
171 | $ re-natal use-figwheel
|
172 | $ lein figwheel android
|
173 | $ react-native run-android
|
174 | ```
|
175 |
|
176 | #### Using Genymotion simulator
|
177 | Set up and start the Genymotion simulator then run
|
178 | ```
|
179 | $ re-natal use-android-device genymotion
|
180 | $ re-natal use-figwheel
|
181 | $ lein figwheel android
|
182 | $ react-native run-android
|
183 | ```
|
184 |
|
185 | #### Using real Android device
|
186 | To run figwheel with real Android device please read [Running on Device](https://facebook.github.io/react-native/docs/running-on-device-android.html#content).
|
187 | To make it work on a USB connected device I also had to run:
|
188 | ```
|
189 | $ adb reverse tcp:8081 tcp:8081
|
190 | $ adb reverse tcp:3449 tcp:3449
|
191 | ```
|
192 | Then:
|
193 | ```
|
194 | $ re-natal use-android-device real
|
195 | $ re-natal use-figwheel
|
196 | $ lein figwheel android
|
197 | $ react-native run-android
|
198 | ```
|
199 |
|
200 | #### Switching between Android devices
|
201 | Run `use-android-device` to configure device type you want to use in development:
|
202 | ```
|
203 | $ re-natal use-android-device <real|genymotion|avd>
|
204 | $ re-natal use-figwheel
|
205 | $ lein figwheel android
|
206 | ```
|
207 |
|
208 | ### Developing iOS and Android apps simultaneously
|
209 | ```
|
210 | $ re-natal use-figwheel
|
211 | $ lein figwheel ios android
|
212 | ```
|
213 |
|
214 | ---
|
215 |
|
216 | ### Using external React Native Components
|
217 |
|
218 | Lets say you have installed an external library from npm like this:
|
219 | ```
|
220 | $ npm i some-library --save
|
221 | ```
|
222 |
|
223 | And you want to use a component called 'some-library/Component':
|
224 | ```clojure
|
225 | (def Component (js/require "some-library/Component"))
|
226 | ```
|
227 | This works fine when you do `lein prod-build` and run your app.
|
228 |
|
229 | The React Native packager statically scans for all calls to `require` and prepares the required
|
230 | code to be available at runtime. But, dynamically loaded (by Figwheel) code bypasses this scan
|
231 | and therefore requiring the custom component fails.
|
232 |
|
233 | In re-natal this is solved by adding all dependencies in index.*.js file which is scanned by React Native packager.
|
234 |
|
235 | #### Using auto-require
|
236 |
|
237 | To enable auto-require feature you have to run command:
|
238 | ```
|
239 | $ re-natal enable-auto-require
|
240 | ```
|
241 | From now on, command `use-figwheel` will scan for all required modules and generate index.*.js with all required dependencies.
|
242 | You will have to re-run `use-figwheel` command every time you use new modules via `(js/require "...")`
|
243 |
|
244 | This feature is available since re-natal@0.7.0
|
245 |
|
246 | #### Manually registering dependencies with use-component command
|
247 |
|
248 | You can register a single dependency manually by running `require` command:
|
249 | ```
|
250 | $ re-natal require some-library/Component
|
251 | ```
|
252 | or for a platform-specific component use the optional platform parameter:
|
253 | ```
|
254 | $ re-natal require some-library/ComponentIOS ios
|
255 | ```
|
256 | Then, regenerate index.*.js files:
|
257 | ```
|
258 | $ re-natal use-figwheel
|
259 | ```
|
260 | Lastly, you will have to restart the packager and reload your app.
|
261 |
|
262 | NOTE: If you mistyped something, or no longer use the component and would like to remove it,
|
263 | manually open `.re-natal` and fix it there (it's just a list of names in JSON format, so the process should be straight forward).
|
264 |
|
265 | #### Scanning for dependencies with require-all command
|
266 |
|
267 | If you have used new modules in your code you can run:
|
268 | ```
|
269 | $ re-natal require-all
|
270 | ```
|
271 | This will scan your code for `(js/require ...)` calls and add new required modules automatically.
|
272 | After this, you still need to run `use-figwheel` command to regenerate index.*.js files.
|
273 |
|
274 | ## REPL
|
275 | You have to reload your app, and should see the REPL coming up with the prompt.
|
276 |
|
277 | At the REPL prompt, try loading your app's namespace:
|
278 |
|
279 | ```clojure
|
280 | (in-ns 'future-app.ios.core)
|
281 | ```
|
282 |
|
283 | Changes you make via the REPL or by changing your `.cljs` files should appear live
|
284 | in the simulator.
|
285 |
|
286 | Try this command as an example:
|
287 |
|
288 | ```clojure
|
289 | (dispatch [:set-greeting "Hello Native World!"])
|
290 | ```
|
291 |
|
292 | ## Running on Linux
|
293 | In addition to the instructions above on Linux you might need to
|
294 | start React Native packager manually with command `react-native start`.
|
295 | This was reported in [#3](https://github.com/drapanjanas/re-natal/issues/3)
|
296 |
|
297 | See this [tutorial](https://gadfly361.github.io/gadfly-blog/2016-11-13-clean-install-of-ubuntu-to-re-natal.html) on how to set up and run re-natal on a clean install of Ubuntu.
|
298 |
|
299 | See also [Linux and Windows support](https://facebook.github.io/react-native/docs/linux-windows-support.html)
|
300 | in React Native docs.
|
301 |
|
302 | ## Support of UWP and WPF apps (using react-native-windows)
|
303 |
|
304 | To start new project with UWP app:
|
305 | ```
|
306 | $ re-natal init FutureApp -u
|
307 | ```
|
308 |
|
309 | To start new project with WPF app:
|
310 | ```
|
311 | $ re-natal init FutureApp -w
|
312 | ```
|
313 |
|
314 | Existing projects can also add windows platforms any time using commands:
|
315 | ```
|
316 | $ re-natal add-platform windows
|
317 |
|
318 | or
|
319 |
|
320 | $ re-natal add-platform wpf
|
321 | ```
|
322 | Note: for projects generated with re-natal version prior to 0.4.0 additional windows builds will not be added automatically to `project.clj`.
|
323 | Workaround is to generate fresh windows project and copy-paste additional builds manually.
|
324 |
|
325 | ## Production build
|
326 | Do this with command:
|
327 | ```
|
328 | $ lein prod-build
|
329 | ```
|
330 | Follow the [React Native documentation](https://facebook.github.io/react-native/docs/signed-apk-android.html) to proceed with the release.
|
331 |
|
332 | #### Advanced CLJS compilation
|
333 | ```
|
334 | $ lein advanced-build
|
335 | ```
|
336 | The ReactNative externs are provided by [react-native-externs](https://github.com/mfikes/react-native-externs)
|
337 | Other library externs needs to be added manually to advanced profile in project.clj
|
338 |
|
339 | ## Static Images
|
340 | Since version 0.14 React Native supports a [unified way of referencing static images](https://facebook.github.io/react-native/docs/images.html)
|
341 |
|
342 | In Re-Natal skeleton images are stored in "images" directory. Place your images there and reference them from cljs code:
|
343 | ```clojure
|
344 | (def my-img (js/require "./images/my-img.png"))
|
345 | ```
|
346 | #### Adding an image during development
|
347 | When you have dropped a new image to "images" dir, you need to restart React Native packager and re-run command:
|
348 | ```
|
349 | $ re-natal use-figwheel
|
350 | ```
|
351 | This is needed to regenerate index.\*.js files which includes `require` calls to all local images.
|
352 | After this you can use a new image in your cljs code.
|
353 |
|
354 | ## Upgrading existing Re-Natal project
|
355 |
|
356 | #### Upgrading React Native version
|
357 |
|
358 | To upgrade React Native to newer version please follow the official
|
359 | [Upgrading](https://facebook.github.io/react-native/docs/upgrading.html) guide of React Native.
|
360 | Re-Natal makes almost no changes to the files generated by react-native so the official guide should be valid.
|
361 |
|
362 | #### Upgrading Re-Natal CLI version
|
363 | Do this if you want to use newer version of re-natal.
|
364 |
|
365 | Commit or backup your current project, so that you can restore it in case of any problem ;)
|
366 |
|
367 | Upgrade re-natal npm package
|
368 | ```
|
369 | $ npm upgrade -g re-natal
|
370 | ```
|
371 | In root directory of your project run
|
372 | ```
|
373 | $ re-natal upgrade
|
374 | ```
|
375 | This will overwrite only some files which usually contain fixes in newer versions of re-natal,
|
376 | and are unlikely to be changed by the user. No checks are done, these files are just overwritten:
|
377 | - files in /env directory
|
378 | - figwheel-bridge.js
|
379 |
|
380 | Then to continue development using figwheel
|
381 | ```
|
382 | $ re-natal use-figwheel
|
383 | ```
|
384 |
|
385 | ## Enabling source maps when debugging in chrome
|
386 | To make source maps available in "Debug in Chrome" mode re-natal patches
|
387 | the react native packager to serve \*.map files from file system and generate only index.\*.map file.
|
388 | To achieve this [this line](https://github.com/facebook/react-native/blob/master/packager/react-packager/src/Server/index.js#L413)
|
389 | of file "node_modules/react-native/packager/react-packager/src/Server/index.js" is modified to match only index.\*.map
|
390 |
|
391 | To do this run: `re-natal enable-source-maps` and restart packager.
|
392 |
|
393 | You can undo this any time by deleting `node_modules` and running `re-natal deps`
|
394 |
|
395 | ## Example Apps
|
396 | * [Luno](https://github.com/alwx/luno-react-native) is a demo mobile application written in ClojureScript.
|
397 | * [Re-Navigate](https://github.com/vikeri/re-navigate) example of using new Navigation component [NavigationExperimental](https://github.com/ericvicenti/navigation-rfc)
|
398 | * [Showcase of iOS navigation](https://github.com/seantempesta/om-next-react-native-router-flux) with react-native-router-flux and Om.Next
|
399 | * [Catlantis](https://github.com/madvas/catlantis) is a funny demo application about cats
|
400 | * [Lymchat](https://github.com/tiensonqin/lymchat) App to learn different cultures. Lym is available in [App Store](https://itunes.apple.com/us/app/lym/id1134985541?ls=1&mt=8).
|
401 | * [Status](https://status.im) ([Github](https://github.com/status-im/status-react/)): a web3 browser, messenger, and gateway to a decentralised world of Ethereum. re-natal + re-frame + cljs + golang
|
402 | * [React Native TodoMVC](https://github.com/TashaGospel/todo-mvc-re-natal) is a mobile application which attempts to implement TodoMVC in Clojurescript and React Native.
|
403 |
|
404 | ## Tips
|
405 | - Having `rlwrap` installed is optional but highly recommended since it makes
|
406 | the REPL a much nicer experience with arrow keys.
|
407 |
|
408 | - Running multiple React Native apps at once can cause problems with the React
|
409 | Packager so try to avoid doing so.
|
410 |
|
411 | - You can launch your app on the simulator without opening Xcode by running
|
412 | `react-native run-ios` in your app's root directory (since RN 0.19.0).
|
413 |
|
414 | - To change advanced settings run `re-natal xcode` to quickly open the Xcode project.
|
415 |
|
416 | - If you have customized project layout and `re-natal upgrade` does not fit you well,
|
417 | then these commands might be useful for you:
|
418 | * `re-natal copy-figwheel-bridge` - just copies figwheel-bridge.js from current re-natal
|
419 |
|
420 | ## Local Development of Re-Natal
|
421 |
|
422 | If you would like to run any of this on your local environment first clone the code to an appropriate place on your machine and install dependencies
|
423 |
|
424 | ```
|
425 | $ git clone https://github.com/drapanjanas/re-natal.git
|
426 | $ cd re-natal
|
427 | $ npm install
|
428 | ```
|
429 |
|
430 | To test any changes made to re-natal, cd to an already existing project or a brand new dummy project:
|
431 |
|
432 | ```
|
433 | $ cd ../already-existing
|
434 | ```
|
435 |
|
436 | and run the re-natal command line like so
|
437 |
|
438 | ```
|
439 | $ node ../re-natal/index.js
|
440 |
|
441 | Usage: re-natal [options] [command]
|
442 |
|
443 |
|
444 | Commands:
|
445 |
|
446 | init [options] <name> create a new ClojureScript React Native project
|
447 | upgrade upgrades project files to current installed version of re-natal (the upgrade of re-natal itself is done via npm)
|
448 | add-platform <platform> adds additional app platform: 'windows' - UWP app, 'wpf' - WPF app
|
449 | xcode open Xcode project
|
450 | deps install all dependencies for the project
|
451 | use-figwheel generate index.*.js for development with figwheel
|
452 | use-android-device <type> sets up the host for android device type: 'real' - localhost, 'avd' - 10.0.2.2, 'genymotion' - 10.0.3.2, IP
|
453 | use-ios-device <type> sets up the host for ios device type: 'simulator' - localhost, 'real' - auto detect IP on eth0, IP
|
454 | use-component <name> [<platform>] configures a custom component to work with figwheel. name is the value you pass to (js/require) function.
|
455 | enable-source-maps patches RN packager to server *.map files from filesystem, so that chrome can download them.
|
456 | copy-figwheel-bridge copy figwheel-bridge.js into project
|
457 |
|
458 | Options:
|
459 |
|
460 | -h, --help output usage information
|
461 | -V, --version output the version number
|
462 | ```
|
463 |
|
464 | You can then run any of the commands manually.
|
465 |
|
466 | [React Native]: https://facebook.github.io/react-native
|
467 | [Reagent]: https://github.com/reagent-project/reagent
|
468 | [Om.Next]: https://github.com/omcljs/om/wiki/Quick-Start-(om.next)
|
469 | [Rum]: https://github.com/tonsky/rum
|