Improving exp publish times for ClojureScript

#1

Context

As a ClojureScript developer, I use the google closure compiler to optimize my JavaScript. In my current project these optimizations takes 9,655,832 bytes of javascript and compiles it down to a single file of 1,518,693 bytes. I can use this file as is for the browser, but react native has additional steps that take a long time.

Problem

React Native has its own transformation step and it’s really slow for my already optimized javascript files. Running exp publish in my project takes 45 minutes in total. 23 minutes to build the bundle for iOS and 17 minutes for Android. To even allow the transformation to run for this long I have to increase the timeout in the metro-bundler that’s set to 5 minutes.

Question

Is there a way to use expo tooling to create a bundle for iOS or Android that doesn’t take tens of minutes?
Would it possible to use expo or the exp command to skip the transformation step for ClojureScript compiled javascript files?

Having this built in to our tools would solve a huge pain point for ClojureScript (and possibly other languages that compile down to JavaScript).

State of the art

There are 2 approaches that I’ve seen and tried to get around this issue.

1. Skip the transformation

Austin Birch was able to skip the transformation step by patching the metro-bundler source code and using his own transformer. This article is now out of date, as the code has changed. Knowing very little about JavaScript, I updated his metro-bundler patch, but I couldn’t get the transformer to work without the bundler exiting with a non-descriptive error message: "map is not defined". I gave up here.

It’d be neat if exp could call the react-native/metro-bundler code in a similar way to avoid transformations on the javascript generated by ClojureScript.

2. Perform transformations on a fake file

peterhazy has a different approach where he doesn’t pass the large compiled javascript file from google closure, he passes a small file which requires all the modules. After this small file gets bundled, he injects the large compiled javascript file into the actual bundle.

I tried this approach and I was able to generate a bundle, but I wasn’t able to use this approach with the existing exp publish command, since it calls the metro-bundler itself. For this to work, exp would have to call the bundler with a fake file itself. There’s a 4 line bash script named build-husk at the root of the project if anyone wants to check it out.

1 Like
#2

That’s a reaaaally long time to wait for a production bundle!

What happens if you use a .babelrc for your project that uses something like https://www.npmjs.com/package/babel-plugin-transform-nothing ? I believe metro respects the .babelrc in the root of your project, so that should work. Note that the babel-preset-expo package does have a number of useful things (rewriting vector icons requires, for example, and also parsing asset requires for upload to our servers) that you’d need to replicate in your cljs build if you disabled babel transforms completely.

cc’ing @nikki as I know cljs support is near and dear to him and he might have some useful pointers.

#3

Thanks for responding. I’m also having this problem… though I haven’t found any solution for publish yet. It seems like exp respects my .babelrc when running in the simulator (I have an ignore: [“main.js”] in there), but… when I go to publish it is trying to run through main.js and hangs again.

UPDATE: I tried the transform-nothing plugin in my .babelrc and it didn’t work. I wonder if it has something to do with the directory where publish is happening?

#4

@petterik how do you adjust the timeout? I’ll take a 40 minute build rather than no-build :slight_smile:

#5

@tobowers I tried to find it on github, as I’m using an old version, but I can’t find the timeout anymore.

It used to be at:
node_modules/metro-bundler/src/JSTransformer/index.js
on line 46:
const TRANSFORM_TIMEOUT_INTERVAL = 301000;

If this information doesn’t help you finding the current location of the timeout, try asking in the #cljsrn channel on clojurians.slack.com

#6

Hi All,
This is still an issue I think - I just did a production build and like @petterik it took me 45 mins - almost exactly in the same ratios as he experienced for IOS / Android. At this point I am just contemplating having a CI server to take my repo each night and publish… but if the Expo team could help here it would really be appreciated…@expo team … any help here ?