Skip to content
This repository has been archived by the owner on Mar 4, 2019. It is now read-only.

Run RN packager in a tmpdir #46

Merged
merged 4 commits into from
Apr 11, 2016
Merged

Conversation

samroberton
Copy link
Contributor

Rather than running the React Native packager in the appdir itself,
create a Boot tmpdir, copy the required node_modules into it, and run
the packager there.

By running from a tmpdir, we can construct exactly the directory
structure that the packager expects from a standard JavaScript
project without needing to structure the boot fileset that way. This
means we can play nicely with other boot tasks that the project might
define -- such as other CLJS builds in the same project (ie
non-React-Native code that shares a codebase with our React Native
code).

Rather than running the React Native packager in the appdir itself,
create a Boot tmpdir, copy the required node_modules into it, and run
the packager there.

By running from a tmpdir, we can construct exactly the directory
structure that the packager expects from a standard JavaScript
project without needing to structure the boot fileset that way. This
means we can play nicely with other boot tasks that the project might
define -- such as other CLJS builds in the same project (ie
non-React-Native code that shares a codebase with our React Native
code).
@samroberton
Copy link
Contributor Author

I appreciate that this is a fairly sizeable change, so let me know if there's any questions I can answer.

I implemented this because I'm introducing a React Native build to an existing project that already has a few React (web) ClojureScript builds, and I was having a lot of difficulty getting React Native to come up correctly in-place.

It might have been possible for me to solve those problems solely by fixing up the handling of different output directories: I'm not sure. I spent some time going down that path, and failed, but that was probably before I understood some more of the under-the-hood details of how boot-react-native and boot itself all fit together.

In any case, I prefer this solution -- where all intermediate boot-react-native output artefacts go to a temp directory only, never to the actual app/node_modules directory -- because it gives greater confidence that the build is correct and reproducible (eg the bundle task can't be just accidentally picking up some old code that the start-rn-packager task has left in node_modules). It has the downside of introducing quite a lot of copying (in the form of hard-linking every one of the thousands of files in the node_modules directory on each build -- you can't hard-link the directories because if you do, boot will delete their contents when it cleans up its temp directories!), but in practice that seems to make much less of a difference to build times than I expected.

Worth mentioning that with these changes, and with adzerk-oss/boot-reload#70, I now have a setup where I can be running the iOS simulator and three separate React web builds, with substantial amounts of code shared between them, and have every single one of them correctly live-reload whenever I save a file. Thanks a ton for the library that's let me get to that point!

I don't know why, but on a few occasions I've seen the bundle task fail,
complaining that it can't find the transformer, if given a relative path
instead of an absolute one. This doesn't appear to happen to the
start-rn-packager task (well, at least, I haven't seen it happen there
so far).
@mjmeintjes
Copy link
Owner

Thanks for this! My apologies, I've been pretty busy the past few weeks, so I haven't had time to check this out a lot.

However, I really like this approach, and think it is the way forward. I've been thinking about adding functionality to automatically include React Native modules, but that'll need something like this to work.

I'll merge this, but as I said, I'm currently pretty busy so my response is going to be slower for the next few weeks. Let me know if want commit access for future changes.

@mjmeintjes mjmeintjes merged commit f8628e4 into mjmeintjes:master Apr 11, 2016
@mjmeintjes
Copy link
Owner

Can you try running the example app on your machine - I'm getting "Cannot find entry file index.android.js in any of the roots" after applying the pull request, running boot dev in the example directory, and then trying to access "http://localhost:8081/index.android.bundle"

@samroberton
Copy link
Contributor Author

I'm a bit embarrassed to admit that I didn't really play much with the example project. No, it doesn't run for me either as-is.

I can get it to run, though, by changing the example's build.boot to have:

(rn/after-cljsbuild :server-url "localhost:8081" :output-dir "main.out")

(ie adding the :output-dir argument), and by accessing http://localhost:8081/main.bundle?platform=android rather than index.android.bundle.

I vaguely remember something that stumped me for a while re index.js v main.js, but off the top of my head I can't recall exactly what.

I've gotta run off right at the moment, but I'll look into this a little more to figure out what's changed. Obviously for the :output-dir "main.out", something's just not defaulting quite right.

@mjmeintjes
Copy link
Owner

Thanks, no big rush.

Looking at it, it seems that we just need to copy over index.android.js and index.ios.js to the work dir in setup-rn-work-dir. However, I'd like to see what you did, as I might be missing something?

@samroberton
Copy link
Contributor Author

Oh, right.

I don't use an index.android.js or index.ios.js, I just modified my React Native app in Xcode / Android Studio to ask for main.bundle directly. I figured that boot-cljs was already outputting a perfectly good app entry point, so the app might as well just load that without the additional indirection. Maybe I'm missing a benefit of doing it the other way, though.

@samroberton
Copy link
Contributor Author

Re being able to see what I did: if you're interested, here's a gist of my dev task -- it's a pipeline with three ClojureScript web builds (student interface, teacher interface, devcards), plus the Clojure server-side (the server-with-repl task) plus the ClojureScript React Native build, all running simultaneously, with all four ClojureScript builds live reloading. (Note that this needs the :only-by-re option to reload from adzerk-oss/boot-reload#70 to get the reloading working correctly all at the same time.)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants