solidnative is a migration of ng-native, which rendered Angular components as native views, to SolidJS. These are the choices made along the way and why. The rules that follow from them are in ARCHITECTURE.md.
ng-native's Fabric engine (retained tree, clone-on-write commit, events, CSS runtime) was already
framework-agnostic, so it was kept as is. Solid drives it through the same host boundary
(packages/fabric/src/host.ts) that the browser host implements. Only the layer above it changed:
Angular's renderer and compiler were replaced by Solid's universal renderer
(solid-js/universal) in @solidnative/platform. Every capability was ported with its tests
before the Angular code was deleted, and the 95% coverage floor was kept.
Solid compiles JSX to direct createElement/insertNode/setProp calls, with no virtual DOM.
That maps onto the engine's mutation API one to one. solid-js/web and React reconciliation are
never in a native bundle; React stays installed only because React Native and Expo need it.
Hermes has no runtime compiler, so JSX and .native.css compile in Metro. A file is Solid when
its name ends in .solid.tsx or it carries the @jsxImportSource @solidnative/platform/solid
pragma; everything else, React Native's own sources included, keeps Expo's transform.
Synchronous signal writes coalesce into one commit on the next microtask, and a run that changed
nothing reaches no completeRoot. The first mount commits synchronously; animations commit from
their own frame callback.
Angular attached component styles through compiler metadata. Solid has none, so a component
applies its sheet with withNativeStyles(sheet, ...), scoped through Solid's owner context to the
nodes it creates. Tailwind and app-wide rules are the root's global sheet.
Angular's DI became useService/ServiceScope in @solidnative/device: device APIs and Expo
modules are scoped Solid services, created lazily and disposed with their owner.
Expo's React Refresh cannot preserve Solid state, so it is off for Solid files. An edit to a
Solid component, sheet or .solid.ts helper disposes the native roots and reloads the JS VM. No
state survives; nothing pretends to.
These only adapted Angular features: provideNativeHttpClient (use fetch), $localize (typed
message catalogs and Intl), the Date.parse shim, @defer (use lazy, Suspense, Show),
the Angular CLI schematics (use create-expo-app --template @solidnative/template or
nx add @solidnative/nx) and the @ng-icons/* sets (now lucide-static or any SVG string).
Everything Angular-derived was renamed: packages moved to the @solidnative/* scope (the
unscoped solidnative npm name is taken), diagnostics read [solidnative] and bundle ids
dev.solidnative.*. The documentation site was rewritten as a Solid DOM app.
- Fabric's event handler. Fabric holds one, and React Native's
ReactFabricclaims it whenever its module loads, which can be late. The Solid root loads that module first, so its own claim is always last. - Duplicate
solid-js. Two copies split the reactive graph silently. Metro resolvessolid-jsfrom the app, once.
The target was React Native's own renderer on the same benchmark. Solid with signals now mounts
within a few percent of React and updates in about a third of its time. The biggest single win
was lowering <View>/<Text> to intrinsics at build time. A C++ commit path was measured and not
built: it could save at most 3-7% of a mount. See performance.md.
No webview, no fork of React Native or Expo, no running third-party React components (their hooks need React's dispatcher; native views and TurboModules they wrap are reachable directly), no SSR or DOM emulation.