Open shirakaba opened 1 month ago
@shirakaba ty for this.
@shirakaba Thank you for this.
With the clear upstream guidance of "just use expo" I'm actually preparing an internal presentation on the current state of expo to present to the RNW team so we can maybe fill some gaps.
I'm not sure how expo prebuild actually works under the covers, but perhaps similar to what you did with react-native autolink-windows
, we now have an react-native init-windows
command for generating the windows
folder (and making updates to metro.config, etc) that is template-based.
Part of a potential todo list would be to create an "expo (prebuild) friendly" template (either new or if possible by fixing the existing ones). I would love to see an example of "here's a new expo project that got at least some parts of windows working (esp wrt. metro)".
With the clear upstream guidance of "just use expo" I'm actually preparing an internal presentation on the current state of expo to present to the RNW team so we can maybe fill some gaps.
Sounds exciting!
I'm not sure how expo prebuild actually works under the covers, but perhaps similar to what you did with react-native autolink-windows, we now have an
react-native init-windows
command for generating the windows folder (and making updates to metro.config, etc) that is template-based.
Ah yes, I've used that. Could you show me where the template lives?
Part of a potential todo list would be to create an "expo (prebuild) friendly" template (either new or if possible by fixing the existing ones). I would love to see an example of "here's a new expo project that got at least some parts of windows working (esp wrt. metro)".
I'm fairly familiar with Expo Prebuild now as I've been contributing some things to it to advance support for react-native-macos
(and NativeScript, but that's another story), so I'd be happy to create a strawman template for out-of-tree platforms.
There are some obstacles to out-of-tree platform support of expo prebuild
and expo create
(which performs a prebuild after downloading a template):
react-native-macos
is lagging on v0.73, which corresponds to Expo SDK v50.dll
files into the template. My PR to fix that landed in SDK v51.create
and prebuild
commands.HelloWorld
placeholder string in any file in the whole template (even a JPG) and it'd get renamed to your desired project name; but now that string-replacement only runs on an explicit list of file paths. It's a simple matter to add new paths (as I show in my not-yet-merged PR to set up the paths to be renamed on macOS projects), but it will need to be done for Windows and it can take 1-2 months for even a simple PR to get merged.ByeWorld
and just run our own renaming script after any usages of create
or prebuild
.Support for other features of the Expo CLI (like the start
command, which seems to ensure that any config plugins have run) are another story and will require further thought.
Will see if I can create that strawman template soon to advance discussions.
@shirakaba since these days the expo
CLI is a dependency of the app, I assume you could fork it in the short term while waiting for PRs to land? Then I suppose you would just have to install the fork after running npx create-expo-app
.
When you say expo create
are you referring to create-expo-app
?
When you say "like the start
command, which seems to ensure that any config plugins have run", do you mean expo run
(which automatically runs prebuild
)?
@wodin For sure, I can fork to my heart's content – just a bit of a harder sell when it comes to putting it into other people's hands. Every step with asterisks increases friction in usage, and we don't want to make people have to commit to using a forked CLI that I might give up on maintaining one day.
When you say
expo create
are you referring tocreate-expo-app
?
I'm referring to create-expo, sorry, yeah.
When you say "like the start command, which seems to ensure that any config plugins have run", do you mean expo run (which automatically runs prebuild)?
Ah yep, I meant expo run:<platform>
(theoretically in this case expo run:windows
), sorry. And exactly, it runs prebuild implicitly if the platform folder is missing.
For some reason, the
@rnx-kit/metro-config
recommended default config didn't work out-of-the-box for me (microsoft/rnx-kit#3257) so I'd love to simplify this.
FYI, as of 1.3.16, @rnx-kit/metro-config
should work out of box with Expo:
const { getDefaultConfig } = require("@expo/metro-config");
const { makeMetroConfig } = require("@rnx-kit/metro-config");
const config = getDefaultConfig(__dirname);
module.exports = makeMetroConfig(config);
Summary
Being an out-of-tree platform, Expo doesn't officially support React Native Windows yet, so l'd like to track what's missing and document the workarounds I'm using for now. FYI @Saadnajmi @tido64 @acoates-ms @EvanBacon.
Motivation
Meta now officially recommend using React Native via a framework such as Expo. A pain-point to adopting out-of-tree platforms (with or without Expo) is setting up all the boilerplate, and Expo has an excellent template system for taming all of that, furthermore enabling easy updates simply by bumping the version of the SDK and running what they call a "prebuild" again to regenerate project files.
Basic Example
No response
Open Questions
I'll knowledge-share how I got
react-native-windows
working alongsidereact-native-macos
andreact-native
(all v73) on Expo SDK 50. It lacks config plugins and prebuild, but you can at least use the same Expo CLI to start and bundle apps.Sorry for the lack of concrete details in some places, as I'm working on a closed-source project, so there's a limit to what I can share; but I'm happy to point to prior art. Will try to help get it all upstreamed.
package.json
Although we're not launching the Windows app using the Expo CLI (i.e.
expo start --windows
, which doesn't exist), we are nonetheless starting a common packager withexpo start
, calling Expo'sregisterRootComponent
as an entrypoint for our app, and using the Expo Babel preset.babel.config.js
We use
babel-preset-expo
instead ofmodule:@react-native/babel-preset
. I was seeing errors about bundling Expo SDK modules without it.metro.config.js
I merged an older metro.config.js from RNTA with this metro.config.js from Expo Orbit, repeating what they did to handle
react-native-macos
to handlereact-native-windows
.For some reason, the
@rnx-kit/metro-config
recommended default config didn't work out-of-the-box for me (https://github.com/microsoft/rnx-kit/issues/3257) so I'd love to simplify this.react-native.config.js
You can omit the
windows
key fromreact-native.config.js
if you want to avoid the Expo CLI trying to autolink and instead take autolinking into your own hands (a trick I learned from here) withreact-native autolink-windows
.I ended up doing this for one reason or another (it's all a bit of a blur). I assume Expo CLI doesn't implement autolinking for Windows, anyway.
index.js
Expo projects do the following:
This does a little more than just calling
AppRegistry.registerComponent()
. From the implementation, you can see that it imports a file for side-effects,Expo.fx
:Expo.fx
accessesexpo-asset
andexpo-font
(which expect to find native classes, e.g.requireNativeModule('ExpoFontLoader')
) without any platform guards for Windows. At runtime, those native modules are missing and thus things break downstream that prevent startup.Note that, even if a Windows implementation of
expo-font
andexpo-asset
were implemented, the React Native Community CLI would fail to autolink it in this case because it only autolinks top-level dependencies, while these are subdependencies of theexpo
npm package. The Expo CLI autolinks even subdependencies.It also hard-codes the appKey as "main" when calling
AppRegistry.runApplication
, so if you've configured yourapp.json
to use an explicit name other than"main"
, then the app will fail to start up.Prior art
Related issues