Last updated on 7 Sep. 2025
Contents
Section Summaries
1. WebView
A WebView is basically a mini web browser engine that can be embedded inside a native app.
It lets the app show web content (HTML, CSS, JavaScript) inside what looks like a normal screen of the app.
The OS provides the WebView component:
-
On Android → it’s based on Chromium (Android System WebView).
-
On iOS → it’s WKWebView (based on Safari’s WebKit engine).
-
On Windows/macOS/Linux → you get equivalents (e.g., WebView2 on
Windows uses the Edge/Chromium engine).
You, as a developer, pass HTML, CSS, and JS (either as a file or a URL)
into the WebView. The WebView engine parses HTML/CSS, runs JS, and renders the UI just like
a browser would. It does not convert HTML/CSS into native UI widgets (e.g., <button>
in HTML is not turned into a native Android Button or iOS UIButton).
Instead, it’s still painted by the web rendering engine inside a
canvas. So it’s web content inside a native wrapper, not true native UI.
To make the WebView useful in real apps, there’s usually a bridge
- Native app ↔ JavaScript inside WebView. Example: In React Native, if you embed a WebView, you can pass
messages/events back and forth (e.g., native code tells JS “user logged
in”, JS tells native “go to screen X”). This bridge lets you mix Native features (camera, GPS, push notifications) and Web features (fast prototyping, reuse web code).
------------------------------
2. WebView vs Native (React Native) Performance (perceived)
-
WebView has slower UI, can feel “non-native” (scrolling, gestures not as
smooth).
-
In React Native, JSX components are compiled into native UI widgets (e.g.,
<Button> → Android Button, iOS UIButton). So it has high
performance, feels like native app.
Apps made with Cordova, Ionic, or Capacitor (older hybrid frameworks) often
felt “non-native” as everything was inside a WebView.
------------------------
3. Expo 'use dom' Directive
In Expo’s DOM Components system, the 'use dom' directive causes that component
to be rendered as HTML inside a WebView on native (Android/iOS). On web, it
renders as normal DOM. Available from Expo SDK 52 onward, this experimental
feature lets you embed web-based UI directly in native apps, on a
per-component basis. As per the Expo guide: “This enables incremental
migration for an entire website to a universal app by moving on a
per-component basis.”
Practical consequences
-
Performance: embedding a WebView adds overhead vs pure native components
(extra memory, startup cost).
-
Styling/HTML fidelity: HTML/CSS in the block will render exactly (good
if you need complex layouts).
-
Interop: you can pass props (via dom) and communicate between native and
the DOM inside the WebView.
-
Migration use-case: great for incrementally moving a web UI into a
universal app without rewriting all markup.
...
Normally, if you want a WebView in React Native, you’d write something like:
import { WebView } from "react-native-webview";
<WebView source={{ html: "<h1>Hello</h1>" }} />
But with Expo’s new DOM Components system ('use dom') automatically wraps
the component’s render output with a managed WebView instance (using the
react-native-webview package under the hood).
...
4. React Native for Windows + react-native-webview
Yes — with React Native for Windows + react-native-webview, you could render
your Strapi backend data (HTML/CSS/JS) inside your Windows “native” app just
like on Android/iOS. It’s the same philosophy: RN abstracts over the WebView
control that the OS already provides.
===========================================
===========================================
Details
Extracts from latter part of chat (it was a continuation of previous chat
session) with ChatGPT (CG), titled, 'React Native for Windows; Web Dev Arch'
on 28 Aug 2025 are given below.
Section 1. WebView
Me: In this chat IFIRC u hv mentioned Webview a few times. What is it?
...
CG:
🔹 What is a WebView?
A WebView is basically a
mini web browser engine that
can be embedded inside a native app.
It lets the app show
web content (HTML, CSS, JavaScript)
inside what looks like a normal screen of the app.
🔹 How WebView works
-
The
OS provides the WebView component:
-
On Android → it’s
based on
Chromium (Android
System WebView).
-
On iOS → it’s
WKWebView (based on
Safari’s WebKit engine).
-
On
Windows/macOS/Linux →
you get equivalents (e.g.,
WebView2 on Windows
uses the Edge/Chromium engine).
-
You, as a developer, pass
HTML, CSS, and JS (either
as a file or a URL) into the WebView.
-
The WebView engine parses HTML/CSS, runs JS, and renders the UI
just like a browser would.
⚠️ But — it does
not convert HTML/CSS into native UI widgets
(e.g., <button>
in HTML is
not turned into a native Android
Button
or iOS
UIButton
). Instead, it’s still
painted by the web rendering engine
inside a canvas.
So it’s
web content inside a native wrapper, not true native UI.
🔹 WebView Bridge
To make the WebView useful in real apps, there’s usually a
bridge:
-
Native app ↔ JavaScript inside WebView.
-
Example: In React Native, if you embed a WebView, you can pass
messages/events back and forth (e.g., native code tells JS “user logged
in”, JS tells native “go to screen X”).
This bridge lets you mix:
-
Native features
(camera, GPS, push notifications).
-
Web features (fast
prototyping, reuse web code).
🔹 So, your guess vs. reality
“OS like Windows and Android provide a WebView bridge like facility to which
HTML and CSS can be passed and then the bridge converts it to Native UI
directives …”
✅ Correct that OS provides a WebView.
❌ But it doesn’t convert HTML/CSS into native widgets. Instead:
👉 That’s why apps made with
Cordova, Ionic, or Capacitor
(older hybrid frameworks) often felt “non-native”: everything was inside a
WebView.
Whereas
React Native / Flutter
don’t use WebView for UI — they map UI components to real native controls (or
draw them with Skia in Flutter’s case).
--------------------
Section 2. WebView vs Native (React Native) Performance (perceived)
CG: .. let’s do a focused comparison
between the three stacks you’ve been working with / exploring:
🔹 UI Rendering Comparison Table
Tech Stack |
How UI is Rendered
|
Native Features Access
|
SEO Friendliness
|
Performance (perceived)
|
Typical Use Case
|
WebView (Cordova / Ionic style)
|
HTML, CSS, JS rendered
inside a WebView engine
(Chromium on Android, WebKit on iOS). Does
not become native
UI — it’s basically a browser-in-an-app.
|
Via a bridge →
native plugins expose camera, GPS, etc., to JS.
|
❌ Poor (since content is behind JS, SEO depends on prerendering).
|
❌ Slower UI, can feel “non-native” (scrolling, gestures not as
smooth).
|
Quick hybrid apps, reusing existing web apps inside a native shell.
|
React Native
|
JSX components are compiled into
native UI widgets
(e.g., <Button> →
Android Button , iOS
UIButton ). No WebView.
|
Direct native modules & APIs (camera, notifications, etc.).
|
❌ Not SEO-friendly, since it’s mobile app only (unless using
React Native Web).
|
✅ High performance, feels like native app.
|
Mobile apps (iOS, Android).
|
Expo for Web (React Native Web)
|
React Native components get mapped to
DOM elements (via
react-native-web ), so
<View> →
<div> ,
<Text> →
<span> . Runs in
browser like a normal React app.
|
Limited to what browsers allow (no native device APIs directly).
|
❌ Same issues as React SPA (hydration, slower first paint, SEO
needs workarounds).
|
⚠️ Medium (not as optimized as Next.js, but decent for
dashboards/internal tools).
|
Cross-platform web version of RN app, dev speed, consistency across
platforms.
|
Next.js
|
React components rendered to
HTML (SSR/SSG) on
server → hydrated into interactive React app on client.
|
Browser APIs only (camera via Web APIs, etc.). Native device APIs
not applicable.
|
✅ Excellent SEO (server-side HTML), ✅ fast first paint.
|
✅ High performance if well-configured (code splitting, SSR
caching).
|
Consumer-facing websites, SEO-heavy apps, blogs, e-commerce,
marketing sites.
|
🔑 Quick Takeaways
-
WebView = fastest way
to ship, worst UX.
-
React Native = best for
mobile native feel.
-
Expo for Web = good for
internal dashboards & cross-platform consistency, but weak in SEO
& first paint.
-
Next.js = best for
public-facing web apps where SEO, speed, and scalability matter.
-------------------------
Section 3. Expo 'use dom' Directive
Me: In a React Native tutorial app that I am studying, for rendering rich
text returned by Strapi backend, few components use 'use dom' directive in top
of their files. For Android app, for these components does Webview come into
play?
[CG was not aware of 'use dom' feature of Expo and so gave wrong answers.
Later ...]
Me: I think this page
https://docs.expo.dev/guides/dom-components/
explains it. Looks like your memory does not have it. Please go through the
page and then respond.
[In an earlier message, I had shared one small component's .tsx file which
used 'use dom'.]
CG: You’re absolutely right—Expo's official documentation includes exactly what
we’ve been discussing! Let me clarify it properly now that we've reviewed
the source:
What the Expo Docs Say About
"use dom"
1. Introducing 'use dom'
—
Expo DOM Components
-
Available from Expo SDK 52 onward, this experimental feature lets you
embed
web-based UI directly in native apps, on a per-component basis.
-
As per the Expo guide: “This enables incremental migration for an entire website to a
universal app by moving on a per-component basis.” Expo Documentation
2. How It Works — WebView-based Rendering
-
A component tagged with
'use dom'
is wrapped with a
WebView
under the hood.
Essentially, it renders actual
HTML for that component inside a WebView
inside your native app.
Expo Documentation
-
So, <div>
,
<img>
, or other typical
HTML tags will render natively in what’s technically a mini browser within
the app.
3. Key Features of DOM Components
-
Unified Bundler Config:
Works seamlessly across web, native, and DOM components.
Expo Documentation
-
Rich Development Experience: Supports React, TypeScript, CSS, Fast Refresh, HMR, debugging via
Safari/Chrome—all inside this WebView environment.
Expo Documentation
-
Pass Props to WebView:
You can customize the underlying WebView via a
dom
prop on the DOM
component—e.g., disabling scrolling.
Expo Documentation
-
Native Actions and Refs: DOM components can receive asynchronous callbacks (native actions) and
support imperative handles for integration with native code.
Expo Documentation
Why This Matters for Your App
-
When your rich-text component has
'use dom'
at the top, it
tells Expo:
-
This is different from your earlier memory of RN Web interpreting
HTML—with 'use dom'
, Expo
is literally embedding a WebView for that component.
So yes—if your tutorial component uses
'use dom'
, it's effectively
using a mini WebView for
that piece of UI, even in the Android/iOS app.
Summary Table
Aspect |
Behavior with
'use dom' in Expo
|
Rendering
|
Renders as
HTML in a WebView
|
Usage |
Primarily for complex web UI blocks, markup, or rapid migration
|
Component hit
|
Wrapped automatically via Expo's WebView bridge
|
Native apps
|
Still fully native except where
'use dom' is applied
|
...
Me: Wait a sec! I think when I asked you about 'use dom', ***your***
memory did not have the right info. about Expo 'use dom' and you gave me
incorrect answers.
CG: Thought for 19s
You’re right — I gave you incorrect info earlier. Sorry about
that, and thanks for calling it out. 👏
Here’s the correct, concise picture and what it means for your
HomeBlock.tsx
:
Short correction
-
I was wrong
when I earlier said
“no WebView unless explicitly used”
in your case.
-
In
Expo’s DOM Components
system, the
'use dom'
directive
does cause
that component to be rendered as HTML inside a
WebView on
native (Android/iOS). On
web, it
renders as normal DOM.
-
So 'use dom'
=
explicit instruction
to use the DOM runtime (which Expo implements by embedding a
WebView on native platforms).
(That’s different from ordinary React Native Web behavior, which
simply maps RN primitives to DOM on the web — the Expo DOM
components mechanism is an explicit WebView-based approach for
rendering HTML/DOM inside native apps.)
What this means for your
HomeBlock.tsx
-
Your file begins with
'use dom';
and
uses
BlocksRenderer
(which emits HTML-like output).
-
On Android/iOS: Expo will render the
BlocksRenderer
output inside a
WebView
(inside the native app). The rest of the component (Image
, View
,
TouchableOpacity
, etc.) remains native.
-
On Web: the
same component will render real DOM nodes in the browser (no
WebView needed there).
-
The dom
prop in
your component signature is there so callers can pass options
to the underlying DOM/WebView instance.
Practical consequences
-
Performance:
embedding a WebView adds overhead vs pure native components
(extra memory, startup cost).
-
Styling/HTML fidelity:
HTML/CSS in the block will render exactly (good if you need
complex layouts).
-
Interop:
you can pass props (via
dom
) and
communicate between native and the DOM inside the WebView.
-
Migration use-case:
great for incrementally moving a web UI into a universal app
without rewriting all markup.
...
Me: The Expo doc page I shared earlier states:
npx expo install react-native-webview
----
My package.json has react-native-webview. What's unusual is
that I do not have to import the Webview from
react-native-webview. It seems that simply using 'use dom'
directive in top of file is enough for Expo to figure out that
WebView is to be used. What do u say?
CG: Exactly ✅ — you’ve noticed the key “magic” here.
Normally, if you want a WebView in React Native, you’d write
something like:
But with Expo’s new
DOM Components
system ('use dom'
):
-
You
do not import
WebView
.
-
Expo’s bundler/runtime sees
'use dom'
at the
top of the file.
-
It automatically wraps the component’s render output with a
managed WebView instance
(using the
react-native-webview
package under the hood).
-
That’s why Expo requires
react-native-webview
as a dependency — even though you never import it yourself,
Expo uses it behind the scenes whenever
'use dom'
is
present.
🔹 Why Expo does it this way
-
Developer convenience: You can write JSX that looks like ordinary web code (<div>
, <table>
,
<ul>
)
without touching WebView APIs.
-
Consistency:
Keeps your component “universal” — same file runs on web (real
DOM) and native (DOM-in-WebView) without changes.
-
Future-proofing: If Expo enhances the DOM runtime later (maybe direct Skia
or RN primitives for certain HTML), your code still works.
So your observation is spot on 👍 —
👉 The presence of
'use dom'
is enough
for Expo to inject a WebView automatically; you don’t import it
yourself.
...
CG: .. let’s make a side-by-side comparison so it’s crystal clear what Expo’s 'use dom'
is doing under the hood.
1.
Manual WebView usage (classic RN way)
If you want to render some HTML content, you’d normally do this:
🔹 Your job:
-
Import WebView
.
-
Write
<WebView>
and pass props (source
, style
, etc.).
-
Maintain the bridge between native and web content manually if
you need interactivity.
2.
Using Expo
'use dom'
Same idea, but Expo hides the WebView boilerplate:
🔹
What happens under the hood:
-
On web →
That really is
<div>
,
<h1>
,
<p>
in
the DOM.
-
On
Android/iOS
→ Expo auto-wraps this whole component in a
WebView
(from
react-native-webview
) and injects your HTML into it.
-
You didn’t import
WebView
, but
it’s being used implicitly.
✅ Comparison Table
Aspect
|
Manual WebView
|
Expo
'use dom'
|
Imports needed
|
Must
import { WebView }
|
No imports, just
"use dom"
|
Code you write
|
<WebView source={{ html: ... }}>
|
Plain JSX with HTML tags (<div> ,
<p> )
|
Web behavior
|
<WebView>
simulating browser
|
Real DOM tags in the browser
|
Native behavior
|
WebView with your HTML
|
Same — WebView under the hood
|
Who manages WebView?
|
You
|
Expo automatically
|
Flexibility
|
Full control of WebView props
|
Limited, but can pass
dom prop
to tweak
|
👉 So, 'use dom'
=
syntactic sugar + integration layer.
Instead of you writing the
<WebView>
boilerplate, Expo injects it automatically and makes your code
look like “just React for the web.”
...
Me: Got it. Two points:
1. The WebView gets pulled in for both Android and iOS Native
apps, I guess. I am on Windows and so cannot generate iOS app but
if I were on Mac, I could do so.
2. It is my choice as developer whether I should use the 'use dom'
convenience provided by Expo OR whether I should directly use a
WebView. I mean, if I want I could rewrite the component to
directly use WebView and not use 'use dom'. am I right?
CG: Exactly ✅ — both of your points are right on target: ...
-------------------------
Section 4. React Native for Windows + react-native-webview
Me: Hmm. It is very interesting to see how WebView provided
by Android and iOS can be used in a native app project to render
HTML/CSS/JS on Android and iOS even if that may be less efficient
than converting it to equivalent Native widgets. I mean, if the
content is small the performance difference for rendering may be
minimal. Great to see Android and iOS provide this functionality
at their OS API level. I presume with Windows it would be similar.
If I were to use React Native for Windows, but not use Expo as it
may not be fully supported, but use React Native WebView
component, then I could have a HomeBlock.tsx component that
renders my STRAPI backend data correctly (as HTML/CSS/JS) on
(Native) Windows. Am I right?
CG: 💯 You got it — your reasoning is spot on. Let’s break it
down:
🔹 WebView = “browser engine inside a native app”
-
Android →
android.webkit.WebView
(Chromium-based since Android 4.4).
-
iOS →
WKWebView
(WebKit
engine, same as Safari).
-
Windows →
WebView2
(based
on Microsoft Edge Chromium).
All three platforms expose these WebView controls in their native
SDKs.
That’s why React Native (and Expo under the hood) can wrap them
with a single cross-platform component:
react-native-webview
.
🔹 Your scenario with React Native for Windows
-
If you
don’t use Expo, but instead use
React Native for Windows, you can still install
react-native-webview
.
-
On Windows, it uses
WebView2
(Chromium-based) to render your HTML/CSS/JS.
-
That means your
HomeBlock.tsx
could display Strapi’s rich-text/HTML output the same way as
on Android and iOS.
-
From your perspective as a developer → same JSX, same props →
it just works across all 3 platforms.
🔹 Trade-offs
-
✅
Quick and easy: You don’t have to map JSON → native UI widgets yourself.
-
✅
Fidelity:
HTML/CSS render exactly as intended.
-
✅
Cross-platform consistency: Your HomeBlock looks identical on Android, iOS, and
Windows.
-
⚠️
Performance: A WebView is heavier than native UI (extra process,
memory). For small chunks of rich text or articles, the
overhead is minimal. But for
entire apps in WebView
(like Cordova days), performance suffers.
-
⚠️
Bridging:
If you need tight integration (e.g. tapping a link triggers
native navigation), you have to wire up messaging between
WebView and RN.
✅ So your statement is correct
Yes — with
React Native for Windows +
react-native-webview
, you could render your Strapi backend data (HTML/CSS/JS) inside
your Windows “native” app just like on Android/iOS.
It’s the same philosophy: RN abstracts over the
WebView control that the OS already provides.
...
Me: The STRAPI rich text JSON block which needs to go through
some blocks renderer to get associated HTML, is incidental. If
instead of STRAPI, I had a backend that sent me HTML fragment as
response (either within a JSON block or even directly), I simply
have to pick up the HTML and pass it on to WebView without having
[need] for any blocks renderer component. Am I on right
track?
CG: Yes ✅ you are absolutely on the right track. ....
Would you like me to also show you how to handle the
security/formatting concerns
(e.g. sanitizing the HTML, limiting scripts, styling consistency)
when injecting backend HTML into a WebView? That’s usually the
next “gotcha” developers run into.
Me: Sanitizing the HTML is an issue, yes. But I was only
trying to get the conceptual picture here. In the tutorial the
STRAPI BlocksRenderer would be handling such sanitizing issues.
.... The central component that makes all this possible on native
(Android/iOS/Windows) is the WebView component/control/API that
the associated OS SDK provides.
[CG agreed with the above.]
Comments
Post a Comment