seantempesta / expo-cljs-template

Expo template for Clojurescript React Native
Eclipse Public License 1.0
304 stars 33 forks source link

Expo 31.0.0 breaks applications for this template #73

Closed jamesnyika closed 5 years ago

jamesnyika commented 5 years ago

On upgrading to Expo 31 SDK, the following error occurs

Unable to resolve module figwheel-bridge from /Volumes/DEVSYS1/apps/giguptal/target/expo/env/index.js: Module figwheel-bridge does not exist in the Haste module map

This might be related to https://github.com/facebook/react-native/issues/4968 To resolve try the following:

  1. Clear watchman watches: watchman watch-del-all.
  2. Delete the node_modules folder: rm -rf node_modules && npm install.
  3. Reset Metro Bundler cache: rm -rf /tmp/metro-bundler-cache-* or npm start -- --reset-cache.
  4. Remove haste cache: rm -rf /tmp/haste-map-react-native-packager-*.

ABI31_0_0RCTFatal __37-[ABI31_0_0RCTCxxBridge handleError:]_block_invoke _dispatch_call_block_and_release _dispatch_client_callout _dispatch_main_queue_callback_4CF CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE __CFRunLoopRun CFRunLoopRunSpecific GSEventRunModal UIApplicationMain main start 0x0

While it looks like a classic cache clearing problem, it does not seem to be so. Any ideas on how it can be resolved ?

thanks

jamesnyika commented 5 years ago

Ok. Found a solution to this.

Understanding

The user.clj file generates the index.js file under target/expo/env/index.js . In that file (user.clj) is a line (#120 as of the writing of this comment) that generates a js/require statement for figwheel. This is why it is all in quotes. This is done early on when preparing the dev environment for figwheel to work and the generated build to run on your device or simulator. I wish @seantempesta could do a writeup someday to explain what all the pre-work does so that we can help better maintain this fabulous template :stuck_out_tongue_winking_eye:

Cause

For some reason that i have not yet devined, the line #120 in env/dev/env/user.clj that says

(js/require "figwheel-bridge")

no longer functions to load up figwheel bridge or to find the .js file. You need to now specify the path to the .js file directly.

I am not sure if the change is due to a new react-native or expo.io change, but this file is not being loaded.

The Fix

To fix portion on line 120 that says

(js/require "figwheel-bridge")

to

(js/require "../../../js/figwheel-bridge")

Everything else should work perfectly otherwise.

Possible Related Bugs

You might want to see another issue I had to fix when doing this upgrade too here (bug 74)

Limitations

This fixes dev builds. If it affects prod I will update this comment otherwise assume it fixes both.

jamesnyika commented 5 years ago

@seantempesta
I would appreciate your thoughts on this fix and if you have a better solution to offer. For now this helped me keep moving. Thank you for everything you do for this project.

seantempesta commented 5 years ago

Huh. That's strange. I guess the search path was changed and it's no longer picking it up? I'm reopening the issue until I can patch this.

Thank you @jamesnyika for tracking this bug down!

jamesnyika commented 5 years ago

@seantempesta Well... I have worse news... At least dev work will work out ok. But the production build will not work at all.

Problem : Cannot build and run in Expo or on device, an application using Expo SDK 31

When you upgrade to Expo 31, everything builds fine but you get this terrible error that I have a spent a week trying to track down.

screen shot 2018-12-18 at 10 11 32 am

What Works:

Changing your production build optimizations to :simple or :none works fine for the use cases I tried (my application and a brand new application created using this template). However, :advanced optimizations break completely with very little information to track down the problem.

Hypothesis

I thought the problem might have been the google closure compiler producing code with missing externs or symbols being munged and not being seen but the same code with a different (older version of the EXPO SDK - I tried SDK 26) works just fine. So that is probably the wrong path. So I am firmly of the opinion it is either something the @expo team put in that is causing closure optimized code to fail.

Reproduce Error

This first portion installs expo 26 I believe.


and project.clj is 
```` clojure
(defproject comp "0.1.0-SNAPSHOT"
            :description "FIXME: write description"
            :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"]
                 [org.clojure/clojurescript "1.10.238"]
                 [binaryage/oops "0.5.8"]
                           [reagent "0.7.0" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server cljsjs/create-react-class]]
                           [re-frame "0.9.3"]
                           [react-native-externs "0.1.0"]]
            :plugins [[lein-cljsbuild "1.1.4"]
                      [lein-figwheel "0.5.14"]]
            :clean-targets ["target/" "main.js"]
            :aliases {"figwheel"        ["run" "-m" "user" "--figwheel"]
                      ; TODO: Remove custom extern inference as it's unreliable
                      ;"externs"         ["do" "clean"
                      ;                   ["run" "-m" "externs"]]
                      "rebuild-modules" ["run" "-m" "user" "--rebuild-modules"]
                      "prod-build"      ^{:doc "Recompile code with prod profile."}
                                        ["with-profile" "prod" "cljsbuild" "once" "main"]}
            :profiles {:dev  {:dependencies [[figwheel-sidecar "0.5.14"]
                                             [com.cemerick/piggieback "0.2.1"]]
                              :source-paths ["src" "env/dev"]
                              :cljsbuild    {:builds [{:id           "main"
                                                       :source-paths ["src" "env/dev"]
                                                       :figwheel     true
                                                       :compiler     {:output-to     "target/expo/not-used.js"
                                                                      :main          "env.expo.main"
                                                                      :output-dir    "target/expo"
                                                                      :optimizations :none}}]}
                              :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}
                       :prod {:cljsbuild {:builds [{:id           "main"
                                                    :source-paths ["src" "env/prod"]
                                                    :compiler     {:output-to          "main.js"
                                                                   :main               "env.expo.main"
                                                                   :output-dir         "target/expo"
                                                                   :static-fns         true
                                                                   :externs            ["js/externs.js"]
                                                                   :infer-externs      true
                                                                   :parallel-build     true
                                                                   :optimize-constants true
                                                                   :optimizations      :advanced
                                                                   :closure-defines    {"goog.DEBUG" false}}}]}}})

and app.json to this

{
  "expo": {
    "name": "comp",
    "description": "No description",
    "slug": "comp",
    "sdkVersion": "31.0.0",
    "version": "1.0.0",
    "orientation": "portrait",
    "primaryColor": "#cccccc",
    "privacy": "public",
    "icon": "./assets/icons/app.png",
    "splash": {
      "image": "./assets/icons/loading.png",
      "resizeMode": "contain",
      "backgroundColor": "#ffffff"
    },
    "ios": {
      "supportsTablet": true
    }
  }
}

Conclusions

please help if you can @seantempesta @expo @jigkoxsee

@jigkoxsee might have some information because that fork seems to be at SDK 30. What are you doing different ?

thanks

seantempesta commented 5 years ago

I've seen that type of error before and it's unrelated to Expo. Unless you are super careful it's really easy to break applications in general with advanced compilation. Are you using a library like cljs-oops for accessing javascript objects?

jamesnyika commented 5 years ago

I am using [binaryage/oops "0.6.4"] Can you describe the precise problem with these libraries..should I just remove them and find another way around doing what I wanted to do ?

jamesnyika commented 5 years ago

Luckily it is only one place I am using the ocall function (right in my core.cljs file - to register the root component) . What other libraries might cause trouble... here is my project.clj file

(defproject giguptal "0.9.5"
            :description "Test of RN"
            :url "http://none.com"
            :license {:name "No License - All rights Reserved"
                      :url  "http://none.com"}
            :dependencies [
                           [org.clojure/clojure "1.9.0"]
                           [org.clojure/clojurescript "1.10.439"]
                           [org.clojure/core.async "0.4.490"]
                           [com.andrewmcveigh/cljs-time "0.5.2"]
                           [com.lucasbradstreet/cljs-uuid-utils "1.0.2"]
                           [io.replikativ/hasch "0.3.5"]
                           [com.taoensso/timbre "4.10.0"]
                           [binaryage/oops "0.6.4"]
                           ;;[cljs-info "1.0.0"]
                           [com.rpl/specter "1.1.2" :exclusions [org.clojure/clojure org.clojure/clojurescript]]
                           [reagent "0.7.0" :exclusions [cljsjs/react cljsjs/react-dom cljsjs/react-dom-server cljsjs/create-react-class]]
                           [reagent-utils "0.3.1"]
                           [re-frame "0.10.6"]
                           [posh "0.5.5"]                   ;; DO NOT UPGRADE> NULL exception in v5.6 beware
                           [datascript "0.17.0"]
                           [org.clojure/core.match "0.3.0-alpha5"]
                           [tongue "0.2.4"]                 ;; provides translation for i18n purposes
                           [cljs-react-navigation "0.1.3"]
                           [react-native-externs "0.2.0"]
                           [haslett "0.1.2"]                ;; websocket library for CLJS
                           [re-frisk-remote "0.5.5"]        ;; need this for viewing contents of the app db
                           [shodan "0.4.2"]                 ;; used to pretty print the logs

                           ]

            :plugins [[lein-cljsbuild "1.1.4"]
                      [lein-figwheel "0.5.14"]
                      [lein-kibit "0.1.5"]
                      [lein-ancient "0.6.15"]
                      [lein-re-frisk "0.5.8"]
                      ;;we have lein-re-frisk in our ~/.lein/profiles.clj
                      ]
            :clean-targets ["target/" "main.js"]
            :aliases {"figwheel"        ["run" "-m" "user" "--figwheel"]
                      ; TODO: Remove custom extern inference as it's unreliable
                      ;"externs"         ["do" "clean"
                      ;                   ["run" "-m" "externs"]]
                      "rebuild-modules" ["run" "-m" "user" "--rebuild-modules"]
                      "prod-build"      ^{:doc "Recompile code with prod profile."}
                                        ["with-profile" "prod" "cljsbuild" "once" "main"]}

            ;;do not change the dependencies below for figwheel. Seems to break something
            :profiles {:dev  {:dependencies [[figwheel-sidecar "0.5.14"]
                                             [com.cemerick/piggieback "0.2.1"]]

                              :source-paths ["src" "env/dev"]
                              :cljsbuild    {:builds [{:id           "main"
                                                       :source-paths ["src" "env/dev"]
                                                       :figwheel     true
                                                       :compiler     {:output-to     "target/expo/not-used.js"
                                                                      :main          "env.expo.main"
                                                                      :output-dir    "target/expo"

                                                                      ;;:recompile-dependents false
                                                                      :preloads      [re-frisk.preload]
                                                                      :optimizations :none}}]}
                              :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}
                       :prod {:cljsbuild {:builds [{:id           "main"
                                                    :source-paths ["src" "env/prod"]
                                                    :compiler     {:output-to          "main.js"
                                                                   :main               "env.expo.main"
                                                                   :output-dir         "target/expo"
                                                                   :static-fns         true
                                                                   :externs            ["js/prod_externs.js" "target/expo/inferred_externs.js"]
                                                                   :infer-externs      true
                                                                   :parallel-build     true
                                                                   :optimize-constants true
                                                                   ;:source-map         "main.js.map"
                                                                   :pseudo-names true
                                                                   :pretty-print       true
                                                                   :optimizations      :simple
                                                                   :closure-defines    {"goog.DEBUG" false}}}]}}})
jamesnyika commented 5 years ago

@seantempesta .. it also does not explain why a new application fails to load in the simulator with Expo 31 but is fine on Expo 26. I have also use the oops library since expo 26 and been able to publish just fine. I think it is a likely candidate for this failure but I can't help but feel there is something else that has happened. Anyway, .. give me some ideas of what you would try or if you know the fix.. super..

jamesnyika commented 5 years ago

After investigating this a little further.. the following production profile seems to work. By work here I mean that you can run expo publish and you will be able to see your app on your mobile device in the expo client:

... 
 :prod {:cljsbuild {:builds [{:id           "main"
                                                    :source-paths ["src" "env/prod"]
                                                    :compiler     {:output-to          "main.js"
                                                                   :main               "env.expo.main"
                                                                   :output-dir         "target/expo"
                                                                   :static-fns         true
                                                                   :externs            ["js/externs.js"]
                                                                   :infer-externs      true
                                                                   :parallel-build     true
                                                                   :optimize-constants true
                                                                   :optimizations      :simple
                                                                   :closure-defines    {"goog.DEBUG" false}}}]}}})

When using the simulator, you need to have the Production mode set to DEV for the simulator to load your main.js if it has advanced optimizations.

I am truly at a loss here as to whether it is something on the @expo side or if this is something to do with clojurescript recent changes.

@seantempesta : if someone is running this application and it has simple compilations, do you know if there is any way they can get to the js code ? I just do not want someone being able to view and understand the google closure generated files.. or worse, I do not know if my cljs files converted into js files are also uploaded as part of the bundle..

a-j-douglass commented 5 years ago

Hi @jamesnyika I'm trying to update a cljs app from expo 26 -> 32 and the stuff you've found out has been invaluable. I'm also stuck at 'Can't find variable: a'.

If you want to find the bundled js code for your app, I managed to find it by running in the android studio emulator, and using adb logcat to find

03-02 17:49:21.944 18675 19484 D b : Got cached OkHttp response for https://d1wp6m56sqw74a.cloudfront.net/%40XXXX%2FXXXXX%2F0.1.2%2Fd5ec14d0e914b44f476da6c62014bd51-32.0.0-android.js

Please do let me know if you make any more progress on this.

a-j-douglass commented 5 years ago

I think https://github.com/expo/expo/blob/master/CHANGELOG.md#-breaking-changes-2 might be involved, and that

(def expo (js/require "expo"))
(defn init []
  (dispatch-sync [:initialize-db])
  (ocall expo "registerRootComponent" (r/reactify-component app)))

isn't an acceptable way to call registerRootComponent any more

a-j-douglass commented 5 years ago

ok after some begging in the Expo Developers Slack, I discovered that changing node_modules/metro/src/JSTransformer/worker.js with

--- worker.js    2018-11-21 14:46:01.271844624 -0700
+++ worker.js    2018-11-21 14:45:52.517615272 -0700
@@ -218,7 +218,7 @@
     }

     if (!options.transformOptions.dev) {
-      plugins.push([constantFoldingPlugin, opts]);
+      // plugins.push([constantFoldingPlugin, opts]);
       plugins.push([inlinePlugin, opts]);
     }var _transformFromAstSync =

solves the prod-build 'Can't find variable: a'. problem @titonbarua

jamesnyika commented 5 years ago

@a-j-douglass, @titonbarua I apologize for the delay... I was working some other stuff for a bit. I have not found a way past the problem of advanced compilation. I am stuck at deploying code that only uses :whitespace or :simple.

@seantempesta is probably the only one who can help. I even tried using shadow-cljs to compile - thought it might have to do with how dependencies were being included or arranged but no. Something changed.. but do not know what. Please post here if you find a solution.

alexdao3 commented 5 years ago

@jamesnyika Just wanted to say huge thanks for meticulously detailing the fixes necessary for upgrading to Expo 31.0. I've just had to do it myself and wouldn't know where I'd be if I didn't come across this issue and your thorough investigation

robert-johansson commented 5 years ago

@alexdao3 and @jamesnyika Is there any way you could please post an example project that works with Expo 31 SDK? That would be very helpful. Thank you.

jamesnyika commented 5 years ago

@robert-Johansson I do not have one I can share because they were proprietary. Best suggestion is to use the project.clj file I posted and changes I suggested without advanced compilation and using a minimalist screen or page. However there is a better path... using shadow-cljs. Shadow now can generate output for react native and there is an example minimal app as part of his examples repo. That is the path I took

robert-johansson commented 5 years ago

@jamesnyika That's a great suggestion! Thanks to your advice I found this repository too, looks very nice: https://github.com/PEZ/rn-rf-shadow

prestancedesign commented 5 years ago

Hi @jamesnyika !

This issue can be closed since I have upgraded all dependencies in this PR https://github.com/seantempesta/expo-cljs-template/pull/81.

Best regards.

seantempesta commented 5 years ago

Fixed via #81. Thanks again @PrestanceDesign!

jamesnyika commented 4 years ago

Thank you all!!!!