40+ minutes expo build:web

Hello!

I’m using expo with ClojureScript, which works surprisingly well. expo start, expo start --web, expo publish all work well!

However, whenever I run expo build:web, it takes over 40 minutes. It gets stuck on 89% progress for most of that time, and the node process takes 100%, so apparently it’s doing something. :slight_smile:

Do you have any ideas why this happen?

Hi

I’m interested to know how you’ve set things up.

Did you use the method mentioned in the Expo docs? Or perhaps something based on the shadow-cljs docs?

Are you using reagent, re-frame or something else? Do you use React Hooks?

Is it possible to get source mapping working?

I’ve poked around a little with ClojureScript and Expo but only on Android so far.

How big is this app of yours? Of course 40 minutes is way too long. Just wondering if I should expect to see the same thing with a hello world example or if it would require a lot more code. Also, do you see a spike in RAM/swap using when node is using 100% of your CPU?

I use shadow-cljs with a react native target, put part of my shadow-cljs.edn at the bottom of the post.

I use reagent, however sparingly, because I’m building a game (you can see more here if you’re interested: https://www.reddit.com/r/animalcapital/comments/f0sa36/new_demo_version_up/).
The libraries I utilize the most is expo-three and three.js. I have played around with “just” shadow-cljs + reagent as well though. Works surprisingly well.

Source mapping works great, I haven’t done any config for it, shadow-cljs handles it.

I’ve verified it working for android, ios and web, so I’m happy with it overall. :slight_smile:

The app is pretty big. 4mb code atm. I don’t know if this would be lower if I could set :optimizations :advanced, but I haven’t gotten it to work with three.js (no problem with just reagent, if memory serves). It’s not that big of a deal though, since it’ll be distributed through app store/google play/steam. So I don’t think my game is as size sensitive as other apps.

I haven’t tried expo web:build with a smaller project, so can’t answer that. Have mostly tried expo for app development. :slight_smile:

No spikes, currently building (5-10 minutes in), ram is at 1.24gb atm. But very flat. Not sure how I’d see swap, but disk usage is just 27 written and 53 read so far. Am on MacOS.

Here’s the shadow-cljs.edn. What’s important to note is that I’ve set :autobuild false, and this is because if you run expo start – no worries, code reloading works as expected. However, when running expo build --web, whenever I save a .cljs-file (and shadow-cljs builds it), metro/webpack starts packaging the new js-code (that shadow-cljs will already have loaded…) and then restart the whole app. I’ve spent hours trying to disable this metro/webpack-behaviour, but haven’t had any luck so far. So instead I disable autobuild, and use load-file in the repl. Works well for me. :slight_smile:

  {:target :react-native
   :init-fn test.app/init
   :compiler-options
   {:optimizations :simple}
   
   
   :dev {:external-config    
         {:devtools/config
          {:features-to-install [:formatters :hints]
           :fn-symbol "F"
           :print-config-overrides true}
          :closure-defines {'goog.DEBUG true}
          #_#_:guardrails {}}}
   :release {}

   :output-dir "app"
   :devtools {:autobuild false
              :repl-pprint true
              :repl-init-ns test.game
              :preloads [shadow.expo.keep-awake]}}

Thanks for the answers.

I haven’t tried source mapping actually, but I assumed it wouldn’t work because as far as I understand it shadow-cljs outputs a blob of JavaScript which is then picked up by Metro/Webpack and minified. So shadow-cljs would generate a source map from the ClojureScript to the intermediate blob. I assumed Metro and Webpack would ignore that and generate a source map from the intermediate blob to the final JavaScript bundle. Is that not the case?

4MB of code does seem pretty large and maybe that’s what’s causing the slow builds. Still, 40 minutes is pretty slow :frowning:

It seems to me that this is unlikely to have anything to do with ClojureScript as such. Webpack will be reading JavaScript that just happens to be produced from ClojureScript. So presumably if you had similar JavaScript that was not compiled from ClojureScript it would also have the same problem.

I think it would be worth creating a hello world app in ClojureScript and measuring the build time.

I don’t know too much about the details, but I believe the process you described is correct, and that thheller has found a way to circumvent that. Some more information can be found here: https://clojureverse.org/t/upgrading-the-react-native-support/4669
In this case I’m just a happy, dumb user. :^)

Yeah, I don’t think it has to do with CLJS in and of itself.

Testing a hello world-app sounds like a good idea, maybe I’ll get some more clues. :slight_smile:

1 Like

Thanks for the link. I see this is the relevant part:

thheller commented on Mar 5, 2019

[…]
Even then it only works when running in Chrome.

Aha, good to know. I develop in Chrome personally. Then I’ve tested the built game on Safari and Chrome, where it works. :slight_smile: