Closed ghost closed 7 years ago
True, need to extend command re-natal use-component
to accept platform option, if provided it would add to platform specific list in .re-natal file. Then, index.*.js could be generated combining common and platform-specific components
Any chance we could change direction on this? I recently came back to cljsrn development after a two month break and spent at least two hours banging my head against the wall because I forgot to issue a use-component
command.
What about creating a react-requires.cljs
file with require statements in it? We could have figwheel generate the index.ios.js and index.android.js files from it AND separately build the rest of the project with it just being required.
(ns future-app.react-requires)
(defonce React (js/require "react"))
(defonce ReactNative (js/require "react-native"))
(defonce Platform (aget ReactNative "Platform"))
(declare IOSModule)
(declare AndroidModule)
(if (aget Platform "ios")
(defonce IOSModule (js/require "react-native-ios-specific"))
(defonce AndroidModule (js/require "react-native-android-specific")))
The goal being to stop using a separate process to require modules. We can also inject other code as necessary (including images files in the images directory?).
Because the current way of doing things is confusing to new developers ... and my poor memory. :)
Sure @seantempesta, I like the idea. Getting rid of use-component
would be the best. But I do not fully understand what technically you mean by
figwheel generate the index.ios.js and index.android.js from it
The problem is that, say, I have compiled namespace future-app.react-requires (which is google closure code) I somehow need this js code to be required from my generated index.*.js file so that packager prepares all required modules.
Please correct me if I'm wrong (as I'm uncertain about how things are actually working), but if you had something like this (I'm just writing pseudo code):
(ns future-app.react-requires)
(defonce React (js/require "react"))
(defonce ReactNative (js/require "react-native"))
(defonce OtherModule (js/require "react-native-other-module"))
(ns future-app.ios.core
(:require [future-app.react-requires]
[reagent.core :as r]))
;;; normal re-natal app code
(defn init
....
(ns future-app.figwheel-loader
(:require [future-app.react-requires :refer [ReactNative]]
[reagent.core :as r]))
(defonce AppRegistry (aget ReactNative "AppRegistry"))
(defonce Text (aget ReactNative "Text"))
(defonce View (aget ReactNative "View"))
(defn app-root []
(fn []
[:> View {}
[:> Text {} "Figwheel Loading..."]]))
(.registerComponent AppRegistry "FutureApp" #(r/reactify-component app-root))
;; Additional code to launch figwheel and load the app ...
So if you have figwheel compiling index.ios.js
using only figwheel-loader.cljs
with simple
compilation, it would produce a working index.ios.js
file that the react packager could consume, parse out the requires and bootstrap the app.
As a separate figwheel target you compile future-app.ios.core
with optimizations: none
which builds the whole app (and in this app you also require react-requires.cljs
.
Okay, so this is the part I don't fully understand, but somehow you are loading figwheel and dynamically loading the app. This part would go after the AppRegistry
section.
Basically, if we wrote the figwheel-bridge.js
code in clojure (or maybe you can load it from future-app.figwheel-loader
?) you could share the react-requires namespace. Then if the user changes it, it would trigger a rebuild of both the index.ios.js file and the app. The packager would be happy and so would the app.
With optimizations :simple
its all good since compilation produces a single file with all deps included.
And there are several problems with optimizations :none
.
One problem is that produced target file (in re-natal it is named not-used.js
) is not what can be used with RN. So instead of that, in re-natal we generate a static index.ios.js file to bootstrap the app and load all dependencies (in cljs_deps.js) dynamically using just eval
. Currently I see no way of producing usable index.*.js with just clojusecript compiler, I have tried playing around withtarget :nodejs
but wasn't able to find a way of making it work so far.
Second problem is that RN packager does not understand closure module/dependency system. So, the bundle prepared by packager does not contain the dependencies. In other words, packager is supposed to do something similar to what is the output when we compile code with optimizations :simple
- resolve all deps and produce one js bundle with all deps. This is why re-natal need to load all js files dynamically even when loading app for the first time (and not only when figwheel needs to reload something). Since RN packager can not follow the dependencies of the app itself, it also does not know what additional modules which are require
'd by the app. So the current workaround is to put those require
s directly in index.ios.js which is served by packager.
I like the improvement idea that these requires could be taken from some namespace instead of adding them manually (to .re-natal config) with use-component
command. I will try to make it work when I have enough time. But again, I do not see it working the way you described it.
Anyways, probably the best solution would be is to teach somehow the RN packager to build the bundle out of the google closure compiled files in optimizations :none
. This would remove most of the current hacks. But, I am not feeling capable of learning JS and the packager that deep to do that :) I think BRN tool is much closer to this than re-natal, need to look deeper how things are done there.
I tried to mock up what I was talking about and realized this is a lot more complicated than I thought. I think you're right that our best bet is to get the react native package manager consuming google closure modules, and until then your solution seems to be the best alternative.
When use ios or android only modules in the same project, the index.ios.js and index.android.js will include wrong modules, for example:
the generated index.*.js file will include all modules, which causes loading errors. Maybe add more directives in the
.re-natal
file to differentiate this kind of case.