Skip to content

Commit 94498b0

Browse files
committed
docs(compiled): preview limits, plugin options, alpha.1 install
- What works: a Preview limits section listing what a compiled release refuses at build time (Angular forms, [ngClass]/[ngStyle], route guards and resolvers, <ng-content>, *pagerItem and the other refused Angular features, binary-only plugins, and on Android an instance's own function for a class method), and the known limit that converted values and arrays are copies. - Angular's supported pipes and RxJS per platform. - Configuration: stubPlugins, and a Plugin options section with an example of pluginReplacements, pluginSources and stubPlugins. - Getting started: core and the compiler must match; the webpack 5.111.1 workaround is gone now that @nativescript/webpack 5.0.39 is out.
1 parent 67babea commit 94498b0

4 files changed

Lines changed: 136 additions & 9 deletions

File tree

‎content/guide/publishing/compiled-configuration.md‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,69 @@ All of them go in `release`, or in a platform's `release`.
3939
| `compiled` | Release builds are compiled instead of bundled for the JavaScript runtime. |
4040
| `pluginReplacements` | `{ 'package': './path.ts' }`: replaces a package with a module of yours that has the same exports. For plugins that only make sense with a JavaScript runtime, such as over-the-air updates. |
4141
| `pluginSources` | `{ 'package': '../checkout' }`: compiles a plugin from a local checkout of its source instead of fetching the published revision. |
42+
| `stubPlugins` | `['nativescript-ui-listview']`: builds binary-only plugins as empty stand-ins. See [Plugin options](#plugin-options). |
4243
| `allowUnimplementedProperties` | Builds even when the app sets a core property the compiled build doesn't apply, with a warning for each. |
4344
| `allowCoreMismatch` | Builds with a `@nativescript/core` other than the one the compiler was made from, with a warning. |
4445
| `allowUntestedFrameworks` | Builds with a framework version outside the [tested ones](/guide/publishing/compiled-differences#tested-framework-versions), with a warning. |
4546
| `narrowKitKeeps` | Android: R8 keeps only what the kit's reflection needs. See [Android](/guide/publishing/compiled-android#minification-r8). |
4647
| `generatedKit` | Android: `false` builds on the older hand-written kit instead of the one generated from core. |
4748

49+
## Plugin options
50+
51+
Paths are relative to the project. `ios.release` and `android.release` can set them per platform: `pluginReplacements`
52+
and `pluginSources` merge by package over the top-level ones, while a platform's `stubPlugins` list replaces the
53+
top-level list.
54+
55+
### `pluginReplacements`
56+
57+
Every import of the package resolves to a TypeScript module of your app instead. The module exports, typed, what
58+
your app uses of the package. The package's native code isn't linked. Use it for a package that only makes sense
59+
with a JavaScript runtime, a JavaScript-only package the compiler can't type, or a binary-only plugin you rewrite.
60+
61+
```ts
62+
// nativescript.config.ts
63+
release: {
64+
pluginReplacements: { 'some-ota-plugin': './release/ota.ts' },
65+
},
66+
```
67+
68+
```ts
69+
// release/ota.ts: the same exports, typed; a compiled release has no bundle to update
70+
export async function sync(): Promise<boolean> {
71+
return false
72+
}
73+
```
74+
75+
### `pluginSources`
76+
77+
The compiler normally fetches the source a plugin's published version was built from, and checks it against the
78+
installed JavaScript. `pluginSources` points a package at a checkout of its TypeScript instead, used as it is and
79+
not checked. Use it for a fork, a private package, or one whose published source can't be found; the build's
80+
message names this option when that happens.
81+
82+
```ts
83+
release: {
84+
pluginSources: { 'some-plugin': '../some-plugin' },
85+
},
86+
```
87+
88+
### `stubPlugins`
89+
90+
`nativescript-ui-listview`, `-sidedrawer`, `-calendar`, `-chart`, `-dataform`, `-autocomplete` and `-gauge` are
91+
binary-only: they ship no TypeScript source, and the build stops on each one it finds. Listing one in
92+
`stubPlugins` builds it as a no-op stand-in. Its views are empty and keep their place in the layout (row, column,
93+
size, margins, classes), their content and events are dropped, and every method does nothing. Its native code isn't
94+
linked, and the build prints a warning naming each stubbed package. Naming any other package is an error.
95+
96+
```ts
97+
release: {
98+
stubPlugins: ['nativescript-ui-listview', 'nativescript-ui-sidedrawer'],
99+
},
100+
```
101+
102+
A stubbed screen renders blank where the plugin was, so this suits trying the rest of an app; replace the plugin
103+
before you ship.
104+
48105
## What your app may need
49106

50107
Most apps need nothing but the flag. Of the apps compiled so far, none changed their own source; some added
@@ -54,6 +111,7 @@ configuration:
54111
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
55112
| A plugin that only makes sense with a JavaScript runtime (over-the-air updates) | `pluginReplacements: { '@norrix/client-sdk': './release/norrix.ts' }` |
56113
| A plugin whose published source can't be found, or doesn't match its JavaScript | `pluginSources: { 'some-plugin': '../some-plugin' }` |
114+
| A binary-only plugin (`nativescript-ui-*`) | `pluginReplacements`, or `stubPlugins: ['nativescript-ui-listview']` |
57115
| You patch a plugin with patch-package | Write the same patch against the plugin's TypeScript source, in `native-release/patches/<package>+<version>.patch`. The compiler compiles the source, not the published JavaScript your patch changes. |
58116
| You patch `@nativescript/core` with patch-package | The compiler recognizes common core patches and applies their effect. One it doesn't recognize stops the build. |
59117
| An `Info.plist` with no `UIApplicationSceneManifest` (older templates) | Nothing: the build adds the template's and says so. |

‎content/guide/publishing/compiled-differences.md‎

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ warning).
4343

4444
Framework features not supported yet stop the build with a message. The main ones:
4545

46-
- **Angular:** under zone.js, a component that doesn't set `changeDetection: ChangeDetectionStrategy.Default`;
47-
pipes other than `async`; a pipe inside `*ngFor`/`@for`; more than one `@Component` in a file. RxJS is a subset.
46+
- **Angular:** under zone.js (`provideZoneChangeDetection()`), a component that doesn't set
47+
`changeDetection: ChangeDetectionStrategy.Default`; more than one `@Component` in a file; the `currency`,
48+
`i18nPlural` and `i18nSelect` pipes (`async`, `date`, `number`, `percent`, `uppercase`, `lowercase`, `titlecase`,
49+
`json`, `slice`, `keyvalue` and your own `@Pipe`s work). RxJS compiles from its source on iOS and is a subset on
50+
Android. Forms, route guards and the other Angular features in [Preview limits](#preview-limits).
4851
- **React:** a component body may hold function declarations, variable declarations and the `return`; a bare
4952
statement such as `useEffect(() => …, [])` on its own line is refused. JSX spread attributes are refused.
5053
- **Vue:** `<style module>`, `<style src>`, a prop `default`, and Options API keys other than `name`, `components`,
@@ -58,6 +61,7 @@ Framework features not supported yet stop the build with a message. The main one
5861
| Native code in `platforms/ios` / `platforms/android` | Linked unchanged |
5962
| Installs objects into the JavaScript engine (`@nativescript/canvas`) | Needs a native counterpart in the kit; canvas has one on both platforms |
6063
| Only meaningful with a JavaScript runtime (over-the-air updates) | Replace it with `release.pluginReplacements` |
64+
| Binary-only, no TypeScript source (`nativescript-ui-*`) | Stops the build; see [Preview limits](#binary-only-plugins) |
6165

6266
Plugin native packaging not carried yet stops the build: a prebuilt `.framework` or `.a` (an `.xcframework` is
6367
fine), a resource `.bundle`, a `.podspec`; on Android, `jniLibs/`, `.so` files, `assets/` and `cpp/` in a plugin's
@@ -101,6 +105,71 @@ The build also stops when:
101105
A few valid constructs still fail later, in the Swift or Kotlin compile, reported at your TypeScript line. The ones
102106
known today are listed in [Not fixed yet](#not-fixed-yet).
103107

108+
## Preview limits
109+
110+
`9.2.0-alpha.1` is a public preview. The features below aren't implemented in a compiled release yet. Rather than
111+
compile to something that silently does nothing, each one stops the build with a message naming the file and what
112+
it found, most of them ending in "is not supported in a release build yet". The JavaScript release supports all
113+
of them.
114+
115+
### Angular
116+
117+
| Refused | Instead, for now |
118+
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
119+
| `@angular/forms` in templates: `[formGroup]`, `formGroupName`, `[formControl]`, `formControlName`, `formArray`, `formArrayName`, `[(ngModel)]`, `[ngModel]`, `(ngModelChange)`, `ngModelGroup`, `ngForm`, `(ngSubmit)` | Bind the view's property and handle its change event (`[text]` with `(textChange)`, `[checked]` with `(checkedChange)`) |
120+
| `[ngClass]`, `[ngStyle]` | `[class.name]="condition"`, `[style.color]="value"` |
121+
| `ngPlural`, `ngPluralCase`, `ngComponentOutlet`; `ngIf`, `ngForOf` or `ngSwitchCase` on an element without `*`; `[ngTemplateOutlet]` anywhere but `<ng-container>` | `@if`, `@for`, `@switch`, or the `*` form |
122+
| `<ng-content>` (content projection), and content inside an element that hosts an attribute-selected component | Pass the data as inputs and render it in the child's own template |
123+
| `*pagerItem`, and structural directives other than `*ngIf`, `*ngFor`, `*ngTemplateOutlet`, `*ngSwitchCase` and `*ngSwitchDefault` | For a pager, `<Pager [items]>` with an `<ng-template let-item>` |
124+
| Route guards and resolvers: `canActivate`, `canActivateChild`, `canDeactivate`, `canMatch`, `canLoad`, `resolve` | Check the condition where you navigate, and load the data in the routed component |
125+
| Route fields other than `path`, `pathMatch`, `component`, `loadComponent`, `redirectTo`, `outlet`, `children`, `loadChildren`, `title` and `runGuardsAndResolvers` (such as `data`, `providers`, `matcher`) | |
126+
| A `path`, `pathMatch`, `redirectTo` or `outlet` that isn't a string literal; a `component` that isn't a class name | |
127+
| Router features other than `withPreloading()` and `withDebugTracing()`; `forRoot` options other than `enableTracing`, `useHash`, `preloadingStrategy`, `scrollPositionRestoration`, `anchorScrolling`, `scrollOffset` | |
128+
| In a routes table outside the app's entry (an NgModule's routing module): `children`, `loadChildren`, `loadComponent`, `outlet`, and a redirect from a path other than `''` | Give the routes to `provideNativeScriptRouter(routes)` in the entry |
129+
| Angular's `routerLink` and `routerLinkActive`, and `nsRouterLinkActive` | `nsRouterLink` |
130+
| `animate.enter`, `animate.leave` and animation events; `(window:…)` and `(document:…)` events | |
131+
| `<ng-container>` with a `#ref`, an event, a directive of yours, or an input other than `ngSwitch`, `ngTemplateOutlet` and `ngTemplateOutletContext` | |
132+
| `<page-router-outlet>` with anything but `name` and `actionBarVisibility="auto"` | |
133+
| `@Component` `host`, `providers`, `viewProviders`, `inputs`, `outputs`, `queries`, `hostDirectives`, `interpolation`, `preserveWhitespaces: true` | `providedIn: 'root'` services; `input()` and `output()` |
134+
| `viewChild()`, `viewChildren()`, `contentChild()`, `contentChildren()`; an `input()` or `model()` option other than `alias`; an `output()` option | `@ViewChild` and `@ViewChildren` |
135+
| In a `@Directive`: fields other than `selector`, `inputs` and `host`; `input()`, `output()`, `model()` and signal queries; lifecycle hooks other than `ngOnInit`, `ngOnChanges`, `ngAfterViewInit`, `ngOnDestroy` | |
136+
| An app `@NgModule`'s `providers` | |
137+
| A plugin element whose `registerElement` meta adds its children itself (`insertChild`, `removeChild`), when it has children; one registered with `skipAddToDom` | |
138+
139+
A name in the first rows that a directive or attribute-selected component of your own takes as an input is
140+
yours, and isn't refused.
141+
142+
### Binary-only plugins
143+
144+
`nativescript-ui-listview`, `-sidedrawer`, `-calendar`, `-chart`, `-dataform`, `-autocomplete` and `-gauge` ship
145+
no TypeScript source, so there is nothing to compile. The build stops and names each one, with two remedies:
146+
replace the package with a module of your app (`release.pluginReplacements`), or build it as an empty stand-in
147+
(`release.stubPlugins`). See [Configuration](/guide/publishing/compiled-configuration#plugin-options).
148+
149+
### Android: an instance's own function for a class method
150+
151+
Assigning a function to a method that a class compiled with your app declares (`logger.log = (m) => …`, where
152+
`log` is a method of `Logger`) stops an Android build: "giving an instance its own Logger.log in place of the
153+
class's method". In the Kotlin output, calls go straight to the class's method, so the assignment would be ignored.
154+
iOS supports it. **Instead:** declare `log` as a field holding a function, or override the method in a subclass.
155+
156+
### Converted values are copies, not the same object (iOS and Android)
157+
158+
This one compiles and runs, and behaves differently. A value with no static type (`any`, parsed JSON, a value from
159+
a non-strict module) becomes a typed object where your code gives it an interface type. That conversion makes a new
160+
object each time:
161+
162+
- The same object read as an interface twice gives two objects: `a === b` is `false`, so are their arrays
163+
(`a.items === b.items`), and a `Map` or `Set` keyed by one doesn't find the other. A memoized selector that
164+
compares its input by identity recomputes every time.
165+
- A typed array (`Float32Array`), or an untyped array, passed to a `number[]` parameter is copied, so what the
166+
function writes into it doesn't reach the caller's array. On Android, an untyped array whose elements already
167+
have the parameter's element type is passed as it is.
168+
169+
**Instead:** give the value its type once, where it enters your code, and pass that typed reference on. Compare
170+
records by an id rather than `===`. Have a function return the values it computes instead of writing into an
171+
array argument, or pass it a `number[]`.
172+
104173
## JavaScript coverage
105174

106175
The compiler is also run against [test262](https://github.com/tc39/test262), the JavaScript conformance suite.

‎content/guide/publishing/compiled-getting-started.md‎

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ before you ship it.
1212

1313
## 1. Install the alpha
1414

15-
The CLI, `@nativescript/core` and `@nativescript/compiler` must be the same alpha:
15+
Install the `alpha` tag of all three. `@nativescript/core` and `@nativescript/compiler` must be the same version:
1616

1717
```bash
1818
npm install -g nativescript@alpha
@@ -22,10 +22,6 @@ npm install @nativescript/core@alpha
2222
npm install --save-dev @nativescript/compiler@alpha
2323
```
2424

25-
::: tip webpack 5.112
26-
Until `@nativescript/webpack` 5.0.39 is out, a new webpack-based project needs `npm install -D webpack@5.111.1` for `ns run` (the JavaScript dev loop). Compiled builds aren't affected.
27-
:::
28-
2925
The CLI runs the compiler from your project's `node_modules`. The build stops if your `@nativescript/core` is not
3026
the version the compiler was made from, or if your framework is outside the
3127
[tested versions](/guide/publishing/compiled-differences#tested-framework-versions).

0 commit comments

Comments
 (0)