diff --git a/content/guide/pathways.md b/content/guide/pathways.md new file mode 100644 index 00000000..b8c945ae --- /dev/null +++ b/content/guide/pathways.md @@ -0,0 +1,37 @@ +--- +title: Two pathways +description: NativeScript is your development runtime, not your production runtime. Write SwiftUI and develop it live, or write TypeScript and compile the release to native code. +contributors: + - NathanWalker +--- + +NativeScript has always run your app on a JavaScript runtime with direct access to every platform API. It now offers +two pathways that keep that development experience and ship **no JavaScript runtime at all**: + +| | 1. SwiftUI, live | 2. TypeScript, compiled | +| --- | --- | --- | +| **You write** | SwiftUI, in an Xcode project | TypeScript with `@nativescript/core` and the framework you like (Angular, Vue, React, Svelte, Solid, plain TypeScript) | +| **While developing** | NativeScript runs your SwiftUI views live: each save is on screen in about 0.15–0.5 s, state kept | `ns run`: the JavaScript runtime with HMR, Chrome DevTools and the whole npm ecosystem, exactly as today | +| **What ships** | Your Swift, built by Xcode as usual | Your app compiled to Swift (iOS) and Kotlin (Android) by `ns build --compiled` | +| **Platforms** | iOS; Android live development, rendered by Jetpack Compose | iOS and Android | +| **Status** | [Preview](/guide/swiftui-live) | [Preview](/guide/publishing/compiled) | + +Both rest on the same idea: **develop live, ship native.** The development runtime gives you instant feedback; the +release is the native code a platform developer would have shipped. + +## Which one fits + +- **You know SwiftUI, or you are starting an iOS-first app in Swift**: take [SwiftUI, live](/guide/swiftui-live). + You keep Xcode, Swift and your project as they are; NativeScript only shortens the edit-to-screen loop. +- **You know web development, or you already have a NativeScript app**: take + [TypeScript, compiled](/guide/publishing/compiled). Nothing changes while you develop. The release build is + compiled instead of bundled. + +The two meet at the release: both ship native code with no engine inside, and both are checked the same way, +pixel by pixel against the build they replace. + +## The JavaScript runtime is not going anywhere + +A release on the JavaScript runtime (`ns build --release`) remains the default and is fully supported. Compiled +releases are opt-in, per build or per platform, and you can switch back with `--no-compiled` at any time. See +[Publishing](/guide/publishing/). diff --git a/content/guide/publishing/compiled-differences.md b/content/guide/publishing/compiled-differences.md new file mode 100644 index 00000000..c2d70a09 --- /dev/null +++ b/content/guide/publishing/compiled-differences.md @@ -0,0 +1,140 @@ +--- +title: "Compiled releases: supported subset and known differences" +description: What a compiled release refuses to build, where it still behaves differently from the JavaScript release, and the versions it is tested with. +contributors: + - NathanWalker +--- + + + +A [compiled release](/guide/publishing/compiled) runs your TypeScript as Swift and Kotlin, against a runtime that +reproduces JavaScript's semantics. This page lists where that stops: what the build refuses, and the differences +known today between a compiled release and the JavaScript release of the same app. Each entry names the platform +it affects. Check every compiled release against its JavaScript release before you ship it +([Checking a compiled release](/guide/publishing/compiled#checking-a-compiled-release)). + +## What the build refuses + +Before anything is compiled, the compiler checks the app (and the plugin code the app reaches) and stops on each of +these with the file, the line and what to write instead. All of them are reported at once. + +| Construct | Why | Instead | +| --- | --- | --- | +| `new Proxy(…)` | No traps without a JavaScript engine | A class with explicit getters and setters, or a `Map` for dynamic keys | +| `Reflect.*` | Not provided by the runtime | The operation itself: `obj[key]`, `key in obj`, `Object.keys(obj)`, `new Cls(...args)` | +| `eval(…)`, `new Function(…)` | There is no engine to evaluate code | A lookup of known functions; or keep this app on the JavaScript release | +| `FinalizationRegistry` | Finalizers do not run | Release the resource explicitly (`dispose()`, `unloaded`, `disposeNativeView`) | +| `SharedArrayBuffer`, `Atomics` | No shared memory between workers | An `ArrayBuffer`, with copies posted between workers | +| `with (obj) { … }` | | Name the object explicitly | +| `import(expr)`, `require(expr)` with a computed specifier | Every module is linked when the app is built | Import each module by a literal path, and choose among those at run time | +| `arguments.callee`, `__proto__` | | A named function; `Object.getPrototypeOf` | +| A bundler constant nothing defines (`declare const __API_URL__`, `process.env.X`) | It would read as undefined at run time | Define it in the bundler config: Vite's `define` and webpack's `DefinePlugin` values are read and compiled in | + +The build also stops, before compiling, when: + +- **The app's `@nativescript/core` is not the core the compiler's kit was generated from.** The kit is core's own + code, compiled; the native widgets it drives come from your installed core, so the two must be the same release. + Install the core version the message names, or the `@nativescript/compiler` released with your core. + `release: { allowCoreMismatch: true }` builds anyway, with a warning. +- **A framework package is outside the versions its support is tested with** (table below). + `release: { allowUntestedFrameworks: true }` builds anyway, with a warning. +- **The toolchain is missing or too old:** Xcode 26 or newer for iOS; JDK 17 or newer and the Android SDK for + Android. + +Other unsupported language and framework constructs are refused by the compiler as it meets them, with the file and +line; see [What stops a build](/guide/publishing/compiled#what-stops-a-build). + +## Tested framework versions + +| Framework | Packages and versions | +| --- | --- | +| Vue | `nativescript-vue` 3.1 and later 3.x | +| Angular | `@nativescript/angular` and `@angular/core` 22.x | +| React | `react-nativescript` 5.x with `react` 18.2 or later 18.x | +| Solid | `@nativescript-community/solid-js` and `solid-js` 2.0 (from 2.0.0-rc.0) | +| Svelte | `svelte-native` 1.x with `svelte` 4.2+, or `svelte-native` 5 (from 5.0.0-alpha.0) with `svelte` 5.50+ | +| Octane | `@nativescript-community/octane` 0.2.4 and later 0.2.x | + +Framework features each front end does not support yet stop the build with a message. The main ones: + +- **Angular:** pipes other than `async`; a pipe inside `*ngFor`/`@for`; `OnPush` under zone.js; more than one + `@Component` in a file. Templates are parsed with the compiler's own `@angular/compiler` 22. +- **React:** a component body may hold function declarations, variable declarations and the `return`; a bare + statement such as `useEffect(() => …, [])` on its own line is refused. JSX spread attributes are refused. +- **Vue:** `