
A recent Microsoft developer blog post makes an interesting assertion about native code that conjures a decades-old argument. What is native code, exactly, and why does anyone feel strongly about this topic, regardless of which side they support?
“React Native for Windows is a great option that allows developers to use JS/React skills and tools to develop native cross-platform applications that target desktop, mobile, web, and more,” Microsoft software engineer Chiara Mooney writes. “React Native uses WinUI under the covers to support many native Windows controls.”
There’s a lot of “native” in there, and that’s confusing. Is it even possible to build “native cross-platform applications” across different platforms, some desktop-based, some mobile, and some web? And what, exactly, is a “native Windows control?”
Sticking mostly to Windows here, most have a vague (mis)understanding that the Win32 API, sometimes just called the Windows API, is the “native” programming environment for Windows apps. And that there are other frameworks and environments–Visual Basic or MFC from 35 years ago, perhaps, or the Windows App SDK today–that “sit” on top of Win32, providing a layer of abstraction to the native APIs with the aim of simplifying or otherwise improving the app development process. This “thing on a thing” approach will remind old-timers like myself of the relationship between Windows and MS-DOS in the pre-NT years. But it also conjures up the notion of trade-offs, where a developer loses some control or performance in return for whatever improvements they get for not going native.
But Win32 is not native code. If you want to be pedantic here–and developers always want to be pedantic, so we must allow for this–Win32 is/was written to abstract even lower-level system code, which is itself an abstraction of the processor architecture-specific code below that.
In fact, it should be obvious to any developer that Win32 essentially being a C++ API today means that it’s not native. C++ is an object-oriented programming (OOP) abstraction built on top of the C language, which was itself built on top of assembly language. Which is built on top of machine code. Which is processor architecture specific. Which explains why these higher level abstractions exist in the first place: With a language like C, for example, the same code can run on different processor architectures. We’ve been abstracting computer hardware since there have been computers. In many ways, native code is a myth. No human beings write native code today, regardless of the platform.
Pedantry aside, perhaps the best way to describe Win32 today is that it is the lowest-level code that any developer, save those that create device drivers, would ever work in today. But no developer would create a meaningful Windows app using C++ and Win32 now. Instead, they would choose between the available frameworks and APIs, typically delivered–as is Win32–via a Software Development Kit (SDK) that might also provide related tools and other resources.
Developers who wish to create Windows apps have always had many choices. Before .NET arrived in 2002, those choices were often language-specific, as per the use of Basic in Visual Basic or C++ in MFC. But with the arrival of the web–and cross-platform options like Java and JavaScript–in the 1990s, things started to change. Windows became less of a focus. Microsoft’s response was to use Java and JavaScript–and HTML and CSS–at first. But through various legal issues and internal debates, it instead created .NET and the C# language to counter what it saw as external threats.
Like Java, C# is a so-called managed language. This means many things, but the code one creates with C# runs within a runtime environment, the .NET runtime, that abstracts the underlying OS. This leads to lots of functional duplication, something developers inside and outside Microsoft complained about in the early days, but also to performance degradation compared to lower-level (Win32) code. But the trade-off, again, was often worth it. Managed code was safer than lower-level code. It could be written in any language compatible with the runtime, not just C#. And in more recent years, it became truly cross-platform. Today, it’s even open source, though that is beside the point here.
Microsoft built a series of frameworks and environments for Windows app developers over the years, some tied to .NET, some that are just what I’ll call “.NET adjacent,” meaning that they use C# and APIs that will be familiar to anyone steeped in .NET programming. Windows Forms was the first, and it was followed up by the much more powerful, but also much more complex, Windows Presentation Foundation (WPF). There were side-trips into mobile/web like Silverlight, which was originally called WPF/E (for “everywhere”). And then Microsoft lost its mind and made the Metro/Windows Runtime (WinRT) apps platform, which was not based on .NET but was .NET adjacent from the perspective of a developer. This evolved into the Universal Windows Platform (UWP), went cross-platform (within Microsoft’s ecosystem), and was mobile-based, not desktop-based, and nowhere close to being native. And … Dear God, it’s hard to keep this all straight.
During this time, a lot changed. User and developer attention on the web shifted to include mobile. Microsoft lost mobile, and Google (Android) and Apple (iOS, and then more) created “native” (read: Not really native) developer environments of their own, further bifurcating things for developers. New cross-platform solutions targeting mobile and web emerged, like Xamarin–now .NET MAUI and part of Microsoft–and Flutter and React Native, a JavaScript-based environment. All of these things are as far from native as is possible. Not that it matters.
For Microsoft’s part, it fought this tide of change until it finally realized it couldn’t. It opened up WinRT/UWP to developers targeting web and mobile with so-called bridges that never went anywhere. It eventually tore up UWP to make it less dependent on specific Windows releases and backed away from mobile apps and made its successor, the Windows App SDK, desktop-based. This environment is not based on .NET either, but it is .NET adjacent, and it gives those developers a way forward. It also gives old-school Win32 developers a way forward, and it’s possible to mix and match .NET and/or Win32 code with new Windows App SDK code to modernize existing apps. Which is basically what that Microsoft blog post that kicks this all off is about.
So we should discuss that for a moment.
Today, most new app development occurs on mobile, the web, or both. Developers can choose between any number of go-to-market strategies, from writing unique “native” apps on each platform–which is expensive, tedious, and problematic–to writing cross-platform apps on a single codebase, which introduces its own problems. Some of these environments, like Flutter and MAUI, bridge the desktop world to some degree, too, so you can write apps that also run on Windows and Mac.
But Windows is mostly legacy at this point. We have some tremendously successful apps, most of which are either web browsers or apps like Office and Photoshop that have been around forever. No one is creating a new version of Office or Photoshop from scratch for Windows. So the goal is modernization. And while the strategy there has evolved over the years and is likely quite different for different companies, Microsoft finally settled on an approach that makes sense. Not just to it, but in general. It is using web technologies, almost universally.
This is pragmatic Because of the shift to web and mobile, Microsoft was forced to port its key Office apps and experiences to those platforms. So it went from supporting Office on two major platforms–Windows and Mac, both desktop-based–to supporting it on five or more platforms, including iOS, Android, and web (and iOS-adjacent platforms too), plus Meta Quest and whatever else. So Microsoft is in the same position as any other developer. It can expend time and resources on creating multiple, duplicative apps “natively” across these platforms. Or it can do what it did. And use web technology that works everywhere.
“Office incrementally adopts new UI frameworks for some experiences while leaving others on legacy frameworks,” Mooney explains. “Over the years, Office has integrated several UI frameworks based on specific goals and platform features. In addition to their internal UI, Office uses React Native, WebView2, and Scene Graph. These client platforms were designed to work together, which is critical for apps like Office that rely on framework interoperability.”
Office now uses React Native for over 40 “Office experiences,” she adds, and it does so because React Native provides “visual consistency across desktop, mobile, and web.” The Office web apps are built entirely in React Native, as are almost all new Office features on desktop and mobile. To work inside the legacy desktop apps, these new React Native features are often packaged inside “content islands” that interact with each other and can pass data between platforms. Office also uses the Windows App SDK on Windows only (and ARM64EC for Windows 11 on Arm) as needed.
But that’s just Office. For the outside world, Microsoft is agnostic today. Having lost developers to the web and mobile, it does for developers what it does elsewhere: It meets you where you are. It has a so-called “native” UI platform, WinUI, that supports C++ and C# and is typically accessed through the Windows App SDK. It supports web developers with React Native, which provides JavaScript-based access to WinUI and the Windows App SDK APIs. And it still supports some older technologies, including WPF, which came back from the dead last year but is just as problematic as ever. Every developer’s needs are different.
But there is one similarity in all this. No developers, almost literally, who target Windows in whatever way are writing native code. That’s as true today as it was in 1990, in some ways. But it’s also a bigger deal today because the trade-offs are disappearing. In 1990 or 2000, for example, one could argue that the performance trade-offs of using Visual Basic or .NET/C+ environment were problematic enough to warrant using the Win32 in specific cases. But those cases are dropping away, thanks largely to massive hardware improvements over those years and to the growing sophistication of developer languages, tools, and frameworks. Today, most videogames are still coded in C++, a cross-platform “thing on a thing” that is nowhere near native. But many are created in higher-level languages and frameworks.
But that’s the nature of coding. What was once high-level is later considered low-level. And to many, C++ now seems like native. But it’s not. Native code is a myth today. And arguing against any higher-level abstraction because it is not native is counterproductive.
But we do argue about this. We argue about this all the time.
A recent forum post about web apps and Firefox triggered an all-too familiar set of arguments that I feel miss the point but also make the point, if that makes sense. One doesn’t “see the benefit of running websites in their own window,” an assertion that would never be made about “native” apps like Notepad and Paint Or, cough, Outlook classic. Some misunderstand web apps to be a way to get web-based content on a computer, when in fact they’re a way to create apps that run on any device using a single codebase. I’m most amused by the idea that web-based email clients are “annoying” when all the recent feature updates to the desktop-based client those users prefer are, wait for it, web-based.
To each his own. And to be clear, I am not ridiculing anyone here. But claiming that a web app is just a website in a window is misguided. It can be that, just as we could write “toy” apps in Visual Basic 30 years ago. But it can be a full-featured app, too. Notion is a powerful web app that I use all day long, every day. A powerful app that I use all day long, every day. Like most of the apps we use, Notion is not a native app. And it doesn’t matter in the slightest. It’s not a website in a window.
Windows has evolved to the point where it puts the three most recently accessed Microsoft Edge tabs into the Alt-Tab application switcher by default. It’s evolved to the point where the bundled apps it provides are based on an uncountable number of technologies that run the gamut from desktop to mobile to web. It’s evolved to the point where Microsoft supports developers who wish to create apps for Windows can do so however they want.
But more broadly, Windows has evolved to the point where native apps are no longer a thing, though some seem to think otherwise. We should evolve along with it.
With technology shaping our everyday lives, how could we not dig deeper?
Thurrott Premium delivers an honest and thorough perspective about the technologies we use and rely on everyday. Discover deeper content as a Premium member.