{"id":153,"date":"2022-07-29T12:00:00","date_gmt":"2022-07-29T19:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/react-native\/?p=153"},"modified":"2022-11-18T03:14:27","modified_gmt":"2022-11-18T11:14:27","slug":"steamline-coreapp-windows","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/react-native\/steamline-coreapp-windows\/","title":{"rendered":"Streamlining app creation with React Native for Windows CoreApp"},"content":{"rendered":"<p>React Native builds on top of the native platform for every OS it runs on; on Windows, this translates to producing a Universal Windows Platform (UWP) app.<\/p>\n<p>We heard from some of our customers that build times for these types of apps can be pretty long &#8211; especially so when building the React Native for Windows framework from source. To mitigate this problem we offer pre-built binary distributions of the framework in the form of NuGet packages. This works pretty well but has a few shortcomings: even when not building the framework itself, building a UWP app requires several build steps behind the scenes (the steps below are what happens for C++\/WinRT apps):<\/p>\n<ul>\n<li>the MIDL compiler is run to turn IDL files into Windows Metadata &#8211; this is required to produce information used by the XAML compiler<\/li>\n<li>the XAML compiler is invoked to convert XAML markup files into C++ code<\/li>\n<li>the MDMerge tool runs to merge all Windows Metadata files from the application<\/li>\n<li>C++\/WinRT is invoked to turn Windows Metadata into C++ projection headers as well as component sources<\/li>\n<li>Only then, the C++ compiler and linker run on the app<\/li>\n<\/ul>\n<p>We set out to address this since a lot of applications won&#8217;t need to customize their native code (e.g. by having XAML UI that isn&#8217;t rendered by RNW); these <em>greenfield<\/em> applications consist of the bare-bones native UWP app, and all of their app logic is confined to their JavaScript (and whatever native modules they require).<\/p>\n<h2>Enter <code>CoreApp<\/code><\/h2>\n<p>To solve this issue, we came up with a very lean, yet flexible, API that enables a UWP Core Application (the kind that doesn&#8217;t require XAML, or any interface definition) to host these <em>greenfield<\/em> apps. We call this API <code>CoreApp<\/code>.\nWhen using the <code>CoreApp<\/code> API, the React Native for Windows framework provides the required <code>XamlApplication<\/code> object as well as a simple XAML <code>Page<\/code> object, which contains a React root view.<\/p>\n<p>This is a new, <em>experimental<\/em> C API that comes in two flavors:<\/p>\n<h3><code>RNCoreAppStart<\/code><\/h3>\n<pre><code class=\"language-cpp\">void RNCoreAppStart(RNCoreAppCallback launched, void *data)<\/code><\/pre>\n<p>This API starts a <code>CoreApp<\/code>, and upon launch, it will call your app back and pass some optional custom data to it as a parameter. The callback enables you to customize a number of parameters, like your bundle name, app name, etc. See CoreApp Schema below for more info.<\/p>\n<h3><code>RNCoreAppStartFromConfigJson<\/code><\/h3>\n<pre><code class=\"language-cpp\">void RNCoreAppStartFromConfigJson(wchar_t const *configJson,\n      RNCoreAppCallback launched,\n      void *data)<\/code><\/pre>\n<p>This API is similar to the previous one but it takes a path to a JSON configuration file. The callback is optional in this case, since more often than not, the configuration file will have all the necessary information.<\/p>\n<p>The <code>launched<\/code> callback above gives you an output <code>RNCoreApp<\/code> structure, where you can set a number of parameters, as well as the <code>data<\/code> parameter that you passed in when you called the <code>CoreApp<\/code> API.<\/p>\n<p>The contents of the <code>RNCoreApp<\/code> structure can be fully set via the JSON configuration file, so next we&#8217;ll take a look at what is in this JSON configuration file.<\/p>\n<h2><code>CoreApp<\/code> schema<\/h2>\n<p>Below are the properties you can set in your app.config.json, with their default values.\nThese properties correspond to properties on the ReactInstanceSettings type.<\/p>\n<pre><code class=\"language-json\">{\n  \"jsBundleFile\": \"index.windows\",\n  \"bundleRootPath\": \"ms-appx:\/\/\/Bundle\/\",\n  \"componentName\": null, \/\/ Required, this is your App's component name\n  \"useWebDebugger\": true,\n  \"useFastRefresh\": true,\n  \"useDeveloperSupport\": true,\n  \"useDirectDebugger\": false,\n  \"requestInlineSourceMap\": true,\n  \"enableDefaultCrashHandler\": false,\n  \"debuggerPort\": 9229,\n  \"sourceBundlePort\": 8081,\n  \"sourceBundleHost\": \"localhost\",\n  \"jsEngine\": \"chakra\", \/\/ possible values: \"chakra\", \"hermes\"\n  \"viewName\": null, \/\/ adds an optional title to the window\n  \"nativeModules\": [\n    {\n      \/\/ this corresponds to the DLL that hosts the native module,\n      \/\/ or the name of the app's exe (or null) if the module is locally defined\n      \"moduleContainer\": null,\n\n      \/\/ the name of the factory function to call to produce a ReactPackageProvider for\n      \/\/ the module; see Using native modules below.\n      \"factory\": null\n    }\n  ],\n  \"properties\": {\n    \/\/ these are all optional. They correspond to properties that will get set in the\n    \/\/ ReactPropertyBag for the instance. Some examples:\n    \"someString\": \"string value\",\n    \"someNumber\": 42.5,\n    \"someBoolean\": true,\n    \"namespace1.namespace2.foo\": 22\n  }\n}<\/code><\/pre>\n<p>For building in Debug mode, your app will usually only need to set a few properties: <code>componentName<\/code>, and the native modules it uses.<\/p>\n<h2>Using native modules<\/h2>\n<p>There are a couple of ways that a <code>CoreApp<\/code> can load native modules.<\/p>\n<p>The simplest way is using the <code>RNCoreAppStartFromConfigJson<\/code> API. As we saw above, this API allows us to pass an optional DLL name to load and a plain C function to call in that DLL, to produce the <code>ReactPackageProvider<\/code> for the module.\nHere&#8217;s what this function would look like:<\/p>\n<pre><code class=\"language-cpp\">extern \"C\" __declspec(dllexport) void *__cdecl MySpecialPackageProvider() {\n  auto provider = winrt::make&lt;MyModulePackageProvider&gt;();\n  void *abi{nullptr};\n  winrt::copy_to_abi(provider, abi);\n  return abi;\n}<\/code><\/pre>\n<p>This snippet will declare a plain C function (this is important so that C++ name mangling mechanism doesn&#8217;t come into play, which is required to be able to use the function name in the JSON file), and export it from the DLL (or the application&#8217;s EXE). It takes no parameters, and simply return a pointer to the package provider for the module.<\/p>\n<p>If using <code>RNCoreAppStart<\/code>, you can create each the <code>ReactPackageProvider<\/code> for each native module you use, and pass it in the <code>packageProvidersAbi<\/code> and <code>packageProvidersAbiCount<\/code> members of the <code>RNCoreApp<\/code> structure:<\/p>\n<pre><code class=\"language-cpp\">app-&gt;packageProvidersAbiCount = 1;\napp-&gt;packageProvidersAbi =\n    reinterpret_cast&lt;void **&gt;(CoTaskMemAlloc(sizeof(void *) * app-&gt;packageProvidersAbiCount));\napp-&gt;packageProvidersAbi[0] = MySpecialPackageProvider();<\/code><\/pre>\n<p>where <code>MySpecialPackageProvider<\/code> is the same as above, only that the <code>extern \"C\" __declspec(dllexport)<\/code> part is not required since we don&#8217;t care about the name, or exporting the function.<\/p>\n<h2>Get Started<\/h2>\n<p>For a sample, take a look at the Calculator CoreApp NuGet project in <a href=\"https:\/\/github.com\/microsoft\/react-native-windows-samples\/tree\/main\/samples\/CalculatorCoreAppNuGet\">\/samples\/CalculatorCoreAppNuGet<\/a>.<\/p>\n<h2>Wrapping up<\/h2>\n<p>With the <code>RNCoreApp<\/code> approach &#8211; combined with NuGet distribution &#8211; we are seeing extremely fast native builds; builds that used to take 15-30 minutes now are down to 10-15 seconds. Because your application actually has very little native code to build, and all of the native logic is encapsulated for you in the React Native for Windows framework, you can get back to being productive in JavaScript, avoid hard-to-diagnose native code errors, and ship your app more quickly!<\/p>\n<p>Compare the calculator sample app (C++\/WinRT, not using NuGet, not using CoreApp), takes almost 15 minutes to build:\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/Calculator.png\" alt=\"Calculator build time from the pipeline\" \/><\/p>\n<p>The same app built using NuGet (but not CoreApp), slashes this to 3.5 minutes:\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/CalculatorNuGet.png\" alt=\"Calculator NuGet build time from the pipeline\" \/><\/p>\n<p>Meanwhile the CoreApp calculator sample clocks in at a speedy 1:49!\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/react-native\/wp-content\/uploads\/sites\/76\/2022\/11\/CalculatorCoreAppNuGet.png\" alt=\"Calculator CoreApp NuGet build time from the pipeline\" \/><\/p>\n<p>Look for this new API to make its debut in our 0.70 release, or try it today in our canary builds.<\/p>\n<p>If you have any feedback, please don&#8217;t hesitate to start a conversation on the <a href=\"https:\/\/github.com\/microsoft\/react-native-windows\">GitHub repo<\/a>!<\/p>\n<p>If you\u2019re interested in getting started with React Native for Windows, check out our website at <a href=\"https:\/\/aka.ms\/reactnative\">aka.ms\/reactnative<\/a>.<\/p>\n<p>You can also follow us on Twitter <a href=\"https:\/\/twitter.com\/reactnativemsft\">@ReactNativeMSFT<\/a> to keep up to date on news, feature roadmaps, and more.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are introducing an API called `CoreApp` to help improve the developer experience for Windows developers.<\/p>\n","protected":false},"author":23376,"featured_media":156,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[2,3,15,6],"class_list":["post-153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-react-native","tag-react-native","tag-react-native-windows","tag-uwp","tag-windows"],"acf":[],"blog_post_summary":"<p>We are introducing an API called `CoreApp` to help improve the developer experience for Windows developers.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/posts\/153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/users\/23376"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/comments?post=153"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/posts\/153\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/media\/156"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/media?parent=153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/categories?post=153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/react-native\/wp-json\/wp\/v2\/tags?post=153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}