"Upgrading" the react-native support

Code-splitting in general requires apps to be structured a little differently yes. You basically just delay requiring something until you actually need it. So in the case of react-native you’d use the appraoch described in the performance docs and apply that directly to the CLJS setup you use.

In there example a require is executed when a button is clicked which then initializes the component that is later used in render.

  didPress = () => {
    if (VeryExpensive == null) {
      VeryExpensive = require('./VeryExpensive').default;
    }

    this.setState(() => ({
      needsExpensive: true,
    }));
  };

The same thing can now be done in shadow-cljs via a bit of extra config.

  {:target :react-native
   :init-fn demo.rn/init
   :chunks {:foo demo.rn-foo/component}
   :output-dir "app"}

Note the extra :chunks config which will create a app/foo.js in additional to the normal app/index.js. So you :init-fn will be executed normally on startup and you can dynamically (js/require "./foo.js") in the code which will return whatever the qualified symbol refered to.

(ns demo.rn-foo)

(defn component [] ...)

So in the above example you’d get the component fn returned by the js/require. You can return anything here (eg. a map via (def component {:whatever true})).

Code-splitting is kinda hard to describe in a general way since it is usually very specific to each app and there is no generic “best” approach that works for everything. The idea I guess for react-native would be to “delay” loading specific screens of an app until they are actually needed. I can’t say how much of a benefit this actually is since I only did the JS side of things and didn’t investigate the whole RN “RAM-bundle” further yet. But according to their docs this should work.

I wrote more about code-splitting in the browser here. You just use js/require instead of the described shadow.lazy stuff.

1 Like

I just started trying shadow-cljs + react-native today, so far it has been among the least painful cljs-setups I’ve tried to do. Awesome job! :smiley: These changes sounds like they’ll make it even more pleasant to use.
BTW would you like a pull-request for your react-native example? I just updated some dependencies in order for expo start --web to work.

3 Likes

Sounds good. I didn’t get a chance to test that yet but was planning to.

Is the upgrade support both :react-native and :expo target?

No, the expo target is deprecated and should no longer be used. Expo should work fine with the :react-native target.

1 Like

@thheller Just used source maps and the react native debugger to fix an issue upgrading expo-sdk to v34. Thanks for all the hard work!

2 Likes