diff --git a/README.md b/README.md index 3ef750b..5c3dd06 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ For more ClojureScript React Native resources visit [cljsrn.org](http://cljsrn.o Contributions are very welcome. ## Status -- Uses [React Native] v0.42.0 +- Uses [React Native] v0.43.4 - Reusable codebase between iOS and Android - Figwheel used for REPL and live coding - Works in iOS (real device and simulator) @@ -31,6 +31,7 @@ Contributions are very welcome. - Source maps available - Supported React wrappers: [Reagent], [Om.Next], and [Rum] +- Support of windows (UWP and WPF) apps - [Unified way of using static images of React Native 0.14+](https://facebook.github.io/react-native/docs/images.html) supported ## Dependencies @@ -65,7 +66,7 @@ To generate a new app, run `re-natal init` with your app's name as an argument: $ re-natal init FutureApp ``` -This will generate a project which uses Reagent v0.5.1. +This will generate a project which uses Reagent v0.6. You may specify the -i option to choose a specific React wrapper: Om.Next, Reagent v0.6 or Rum: ``` @@ -239,18 +240,6 @@ Lastly, you will have to restart the packager and reload your app. NOTE: If you mistyped something, or no longer use the component and would like to remove it, 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). ---- - -### Faster Figwheel hot reloading -Since version 0.22 React Native supports Hot Module Reload. But at least for now, this feature is redundant because we have Figwheel. - -It looks like Figwheel reloads are faster if Hot Moduler Reload is OFF. -Also, the packager is not necessary to watch for changed files - Figwheel does that (except on Linux). - -Two things you can do: - -1. Turn off HMR from the development menu. -2. Start the packager with option `--nonPersistent`. You can use `npm start` for that. ## REPL You have to reload your app, and should see the REPL coming up with the prompt. @@ -280,6 +269,29 @@ See this [tutorial](https://gadfly361.github.io/gadfly-blog/2016-11-13-clean-ins See also [Linux and Windows support](https://facebook.github.io/react-native/docs/linux-windows-support.html) in React Native docs. +## Support of UWP and WPF apps (using react-native-windows) + +To start new project with UWP app: +``` +$ re-natal init FutureApp -u +``` + +To start new project with WPF app: +``` +$ re-natal init FutureApp -w +``` + +Existing projects can also add windows platforms any time using commands: +``` +$ re-natal add-platform windows + +or + +$ re-natal add-platform wpf +``` +Note: for projects generated with re-natal version prior to 0.4.0 additional windows builds will not be added automatically to `project.clj`. +Workaround is to generate fresh windows project and copy-paste additional builds manually. + ## Production build Do this with command: ``` @@ -394,16 +406,17 @@ $ node ../re-natal/index.js Commands: - init [options] create a new ClojureScript React Native project - upgrade upgrades project files to current installed version of re-natal (the upgrade of re-natal itself is done via npm) - xcode open Xcode project - deps install all dependencies for the project - use-figwheel generate index.ios.js and index.android.js for development with figwheel - use-android-device sets up the host for android device type: 'real' - localhost, 'avd' - 10.0.2.2, 'genymotion' - 10.0.3.2 - use-ios-device sets up the host for ios device type: 'simulator' - localhost, 'real' - auto detect IP on eth0, IP - use-component configures a custom component to work with figwheel. name is the value you pass to (js/require) function. - enable-source-maps patches RN packager to server *.map files from filesystem, so that chrome can download them. - copy-figwheel-bridge copy figwheel-bridge.js into project + init [options] create a new ClojureScript React Native project + upgrade upgrades project files to current installed version of re-natal (the upgrade of re-natal itself is done via npm) + add-platform adds additional app platform: 'windows' - UWP app, 'wpf' - WPF app + xcode open Xcode project + deps install all dependencies for the project + use-figwheel generate index.*.js for development with figwheel + use-android-device sets up the host for android device type: 'real' - localhost, 'avd' - 10.0.2.2, 'genymotion' - 10.0.3.2, IP + use-ios-device sets up the host for ios device type: 'simulator' - localhost, 'real' - auto detect IP on eth0, IP + use-component [] configures a custom component to work with figwheel. name is the value you pass to (js/require) function. + enable-source-maps patches RN packager to server *.map files from filesystem, so that chrome can download them. + copy-figwheel-bridge copy figwheel-bridge.js into project Options: diff --git a/package.json b/package.json index 9df9e3a..b45ca0c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "re-natal", - "version": "0.3.7", + "version": "0.4.0", "description": "Bootstrap ClojureScript React Native apps with reagent and re-frame for iOS and Android", "main": "index.js", "author": "Artur Girenko ", diff --git a/re-natal.coffee b/re-natal.coffee index 8ae4363..a586b43 100644 --- a/re-natal.coffee +++ b/re-natal.coffee @@ -36,7 +36,8 @@ ipAddressRx = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/i figwheelUrlRx = /ws:\/\/[0-9a-zA-Z\.]*:/g appDelegateRx = /http:\/\/[^:]+/g debugHostRx = /host\s+=\s+@".*";/g -rnVersion = '0.42.0' +rnVersion = '0.43.4' +rnWinVersion = '0.42.0' rnPackagerPort = 8081 process.title = 're-natal' interfaceConf = @@ -55,8 +56,8 @@ interfaceConf = sources: common: ["events.cljs", "subs.cljs", "db.cljs"] other: [["reagent_dom.cljs","reagent/dom.cljs"], ["reagent_dom_server.cljs","reagent/dom/server.cljs"]] - deps: ['[reagent "0.6.0" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server]]' - '[re-frame "0.8.0"]'] + deps: ['[reagent "0.6.1" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server]]' + '[re-frame "0.9.2"]'] shims: ["cljsjs.react", "cljsjs.react.dom", "cljsjs.react.dom.server"] sampleCommandNs: '(in-ns \'$PROJECT_NAME_HYPHENATED$.ios.core)' sampleCommand: '(dispatch [:set-greeting "Hello Native World!"])' @@ -264,7 +265,7 @@ configureDevHostForAndroidDevice = (deviceType) -> try devHost = resolveAndroidDevHost(deviceType) config = readConfig() - config.android.host = devHost + config.platforms.android.host = devHost writeConfig(config) log "Please run: re-natal use-figwheel to take effect." catch {message} @@ -285,7 +286,7 @@ configureDevHostForIosDevice = (deviceType) -> try devHost = resolveIosDevHost(deviceType) config = readConfig() - config.ios.host = devHost + config.platforms.ios.host = devHost writeConfig(config) log "Please run: re-natal use-figwheel to take effect." catch {message} @@ -397,20 +398,34 @@ copyProjectClj = (interfaceName, projNameHyph) -> edit 'project.clj', [[projNameHyphRx, projNameHyph], [interfaceDepsRx, deps], [platformCleanRx, cleans.join(' ')], [devProfilesRx, devProfiles.join("\n")], [prodProfilesRx, prodProfiles.join("\n")]] updateProjectClj = (platform) -> + proj = readFile('project.clj') + cleans = [] cleans.push "\"index.#{platform}.js\"" cleans.push platformCleanId + if !proj.match(platformCleanRx) + log "Manual update of project.clj required: add clean targets:" + log "#{cleans.join(' ')}", "red" + devProfileTemplate = readFile "#{resources}/dev.profile" devProfiles = [] devProfiles.push devProfileTemplate.replace(platformRx, platform) devProfiles.push devProfilesId + if !proj.match(devProfilesRx) + log "Manual update of project.clj required: add new build to dev profile:" + log "#{devProfiles.join('\n')}", "red" + prodProfileTemplate = readFile "#{resources}/prod.profile" prodProfiles = [] prodProfiles.push prodProfileTemplate.replace(platformRx, platform) prodProfiles.push prodProfilesId + if !proj.match(prodProfilesRx) + log "Manual update of project.clj required: add new build to prod profile:" + log "#{prodProfiles.join('\n')}", "red" + edit 'project.clj', [[platformCleanRx, cleans.join(' ')], [devProfilesRx, devProfiles.join("\n")], [prodProfilesRx, prodProfiles.join("\n")]] init = (interfaceName, projName) -> @@ -461,7 +476,7 @@ init = (interfaceName, projName) -> 'babel-plugin-transform-es2015-block-scoping': '6.15.0' if 'windows' in platforms || 'wpf' in platforms - pkg.dependencies['react-native-windows'] = rnVersion + pkg.dependencies['react-native-windows'] = rnWinVersion fs.writeFileSync 'package.json', JSON.stringify pkg, null, 2 @@ -527,53 +542,59 @@ init = (interfaceName, projName) -> message addPlatform = (platform) -> - config = readConfig() - platforms = Object.keys config.platforms + try + if !(platform of platformMeta) + throw new Error "Unknown platform [#{platform}]" - if platform in platforms - log "A project for a #{platformMeta[platform].name} app already exists" - else - interfaceName = config.interface - projName = config.name - projNameHyph = projName.replace(camelRx, '$1-$2').toLowerCase() - projNameUs = toUnderscored projName + config = readConfig() + platforms = Object.keys config.platforms - log "Preparing for #{platformMeta[platform].name} app." + if platform in platforms + throw new Error "A project for a #{platformMeta[platform].name} app already exists" + else + interfaceName = config.interface + projName = config.name + projNameHyph = projName.replace(camelRx, '$1-$2').toLowerCase() + projNameUs = toUnderscored projName - updateProjectClj(platform) - copySrcFilesForPlatform(platform, interfaceName, projName, projNameUs, projNameHyph) - copyDevEnvironmentFilesForPlatform(platform, interfaceName, projNameHyph, projName, defaultEnvRoots.dev, "localhost") - copyProdEnvironmentFilesForPlatform(platform, interfaceName, projNameHyph, projName, defaultEnvRoots.prod) + log "Preparing for #{platformMeta[platform].name} app." - pkg = JSON.parse readFile 'package.json' - - unless 'react-native-windows' in pkg.dependencies - pkg.dependencies['react-native-windows'] = rnVersion - fs.writeFileSync 'package.json', JSON.stringify pkg, null, 2 - exec 'npm i' + updateProjectClj(platform) + copySrcFilesForPlatform(platform, interfaceName, projName, projNameUs, projNameHyph) + copyDevEnvironmentFilesForPlatform(platform, interfaceName, projNameHyph, projName, defaultEnvRoots.dev, "localhost") + copyProdEnvironmentFilesForPlatform(platform, interfaceName, projNameHyph, projName, defaultEnvRoots.prod) - if platform is 'windows' - log 'Creating React Native UWP project.' - exec "node -e - \"require('react-native-windows/local-cli/generate-windows')('.', '#{projName}', '#{projName}')\" - " + pkg = JSON.parse readFile 'package.json' - if platform is 'wpf' - log 'Creating React Native WPF project.' - exec "node -e - \"require('react-native-windows/local-cli/generate-wpf')('.', '#{projName}', '#{projName}')\" - " + unless 'react-native-windows' in pkg.dependencies + pkg.dependencies['react-native-windows'] = rnWinVersion + fs.writeFileSync 'package.json', JSON.stringify pkg, null, 2 + exec 'npm i' - fs.appendFileSync(".gitignore", "\n\nindex.#{platform}.js\n") + if platform is 'windows' + log 'Creating React Native UWP project.' + exec "node -e + \"require('react-native-windows/local-cli/generate-windows')('.', '#{projName}', '#{projName}')\" + " - config.platforms[platform] = - host: "localhost" - modules: [] + if platform is 'wpf' + log 'Creating React Native WPF project.' + exec "node -e + \"require('react-native-windows/local-cli/generate-wpf')('.', '#{projName}', '#{projName}')\" + " - writeConfig(config) + fs.appendFileSync(".gitignore", "\n\nindex.#{platform}.js\n") - log 'Compiling ClojureScript' - exec 'lein prod-build' + config.platforms[platform] = + host: "localhost" + modules: [] + + writeConfig(config) + + log 'Compiling ClojureScript' + exec 'lein prod-build' + catch {message} + logErr message openXcode = (name) -> try @@ -761,15 +782,10 @@ cli.command 'upgrade' .action -> doUpgrade readConfig(false) -cli.command 'windows' - .description 'add project for UWP app' - .action -> - addPlatform('windows') - -cli.command 'wpf' - .description 'add project for WPF app' - .action -> - addPlatform('wpf') +cli.command 'add-platform ' + .description 'adds additional app platform: \'windows\' - UWP app, \'wpf\' - WPF app' + .action (platform) -> + addPlatform(platform) cli.command 'xcode' .description 'open Xcode project' diff --git a/resources/cljs-reagent6/main_dev.cljs b/resources/cljs-reagent6/main_dev.cljs index 00bedb7..940e363 100644 --- a/resources/cljs-reagent6/main_dev.cljs +++ b/resources/cljs-reagent6/main_dev.cljs @@ -1,5 +1,6 @@ (ns ^:figwheel-no-load env.$PLATFORM$.main (:require [reagent.core :as r] + [re-frame.core :refer [clear-subscription-cache!]] [$PROJECT_NAME_HYPHENATED$.$PLATFORM$.core :as core] [figwheel.client :as figwheel :include-macros true])) @@ -9,9 +10,13 @@ (defn reloader [] @cnt [core/app-root]) (def root-el (r/as-element [reloader])) +(defn force-reload! [] + (clear-subscription-cache!) + (swap! cnt inc)) + (figwheel/watch-and-reload :websocket-url "ws://$DEV_HOST$:3449/figwheel-ws" :heads-up-display false - :jsload-callback #(swap! cnt inc)) + :jsload-callback force-reload!) (core/init) \ No newline at end of file diff --git a/resources/figwheel-bridge.js b/resources/figwheel-bridge.js index a045e99..e5d9a9c 100644 --- a/resources/figwheel-bridge.js +++ b/resources/figwheel-bridge.js @@ -220,7 +220,7 @@ function loadApp(platform, devHost, onLoadCb) { // seriously React packager? why. var googreq = goog.require; - googreq('figwheel.connect.' + platform); + googreq('figwheel.connect.build_' + platform); }); }); } diff --git a/resources/project.clj b/resources/project.clj index 1ec4c22..96bc7cc 100644 --- a/resources/project.clj +++ b/resources/project.clj @@ -3,16 +3,16 @@ :url "http://example.com/FIXME" :license {:name "Eclipse Public License" :url "http://www.eclipse.org/legal/epl-v10.html"} - :dependencies [[org.clojure/clojure "1.9.0-alpha10"] - [org.clojure/clojurescript "1.9.198"] + :dependencies [[org.clojure/clojure "1.9.0-alpha16"] + [org.clojure/clojurescript "1.9.521"] $INTERFACE_DEPS$] :plugins [[lein-cljsbuild "1.1.4"] - [lein-figwheel "0.5.8"]] + [lein-figwheel "0.5.10"]] :clean-targets ["target/" #_($PLATFORM_CLEAN$)] :aliases {"prod-build" ^{:doc "Recompile code with prod profile."} ["do" "clean" ["with-profile" "prod" "cljsbuild" "once"]]} - :profiles {:dev {:dependencies [[figwheel-sidecar "0.5.8"] + :profiles {:dev {:dependencies [[figwheel-sidecar "0.5.10"] [com.cemerick/piggieback "0.2.1"]] :source-paths ["src" "env/dev"] :cljsbuild {:builds [