Skip to content

Commit 74d67a1

Browse files
committed
feat: vite docs updated
1 parent 3920999 commit 74d67a1

3 files changed

Lines changed: 151 additions & 43 deletions

File tree

content/configuration/vite.md

Lines changed: 146 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ contributors:
77

88
All NativeScript apps can be bundled using [Vite](https://vite.dev/). To manage the required configuration, we maintain the `@nativescript/vite` package.
99

10+
Starting with NativeScript CLI 9.1, the Vite dev server is fully integrated into the CLI — `ns debug ios` and `ns debug android` start the dev server, pick a free port, and connect the device automatically. No extra npm scripts are needed.
11+
1012
## Setup
1113

1214
Install the plugin.
@@ -33,7 +35,7 @@ Make sure your `nativescript.config.ts` includes the following to use Vite as th
3335
export default {
3436
// ...
3537
bundler: 'vite',
36-
bundlerConfigPath: 'vite.config.ts',
38+
bundlerConfigPath: 'vite.config.mts',
3739
// ...
3840
}
3941
```
@@ -48,24 +50,23 @@ npx nativescript-vite init
4850

4951
This will:
5052

51-
- Generate a `vite.config.ts` using the detected project flavor (Angular, Vue, React, Solid, TypeScript, or JavaScript) and the corresponding helper from `@nativescript/vite`.
52-
- Add (or update) the following npm scripts in your app `package.json`:
53-
- `dev:ios`
54-
- `dev:android`
55-
- `dev:server:ios`
56-
- `dev:server:android`
57-
- `ios`
58-
- `android`
59-
- Add the devDependencies `concurrently` and `wait-on`.
60-
- Add the dependency `@valor/nativescript-websockets`.
53+
- Generate a `vite.config.mts` using the detected project flavor (Angular, Vue, React, Solid, TypeScript, or JavaScript) and the corresponding helper subpath from `@nativescript/vite`.
54+
- Add the dependency `@valor/nativescript-websockets` (the WebSocket polyfill the HMR client uses to talk to the dev server).
6155
- Append `.ns-vite-build` to `.gitignore` if it is not already present.
6256

63-
After running `init`, you now have two ways to work with Vite:
57+
::: tip Why `vite.config.mts`?
58+
59+
The `.mts` extension keeps the config ESM without setting `"type": "module"` in the app's `package.json` (which NativeScript apps leave unset), avoiding Vite's `configLoader: 'native'` forward-compat warning.
60+
61+
:::
6462

65-
1. HMR workflow
63+
After running `init`, you have two ways to work with Vite:
64+
65+
1. HMR workflow (default — the CLI starts and manages the dev server for you)
6666

6767
```bash
68-
npm run dev:ios
68+
ns debug ios
69+
ns debug android
6970
```
7071

7172
2. Standard dev workflow (non-HMR)
@@ -77,7 +78,7 @@ ns debug android --no-hmr
7778

7879
## Configure
7980

80-
The plugin comes with several framework integrations.
81+
The plugin comes with several framework integrations. Each is imported from its own subpath so unrelated framework tooling is never loaded.
8182

8283
### Vue
8384

@@ -112,36 +113,36 @@ export default defineConfig(({ mode }): UserConfig => {
112113
})
113114
```
114115

115-
### Svelte
116+
### React
116117

117118
```ts
118119
import { defineConfig, mergeConfig, UserConfig } from 'vite'
119-
import { svelteConfig } from '@nativescript/vite/svelte'
120+
import { reactConfig } from '@nativescript/vite/react'
120121

121122
export default defineConfig(({ mode }): UserConfig => {
122-
return mergeConfig(svelteConfig({ mode }), {})
123+
return mergeConfig(reactConfig({ mode }), {})
123124
})
124125
```
125126

126-
### React
127+
### TypeScript (XML view)
127128

128129
```ts
129130
import { defineConfig, mergeConfig, UserConfig } from 'vite'
130-
import { reactConfig } from '@nativescript/vite/react'
131+
import { typescriptConfig } from '@nativescript/vite/typescript'
131132

132133
export default defineConfig(({ mode }): UserConfig => {
133-
return mergeConfig(reactConfig({ mode }), {})
134+
return mergeConfig(typescriptConfig({ mode }), {})
134135
})
135136
```
136137

137-
### TypeScript (XML view)
138+
### JavaScript (XML view)
138139

139140
```ts
140-
import { defineConfig, mergeConfig, UserConfig } from 'vite'
141-
import { typescriptConfig } from '@nativescript/vite'
141+
import { defineConfig, mergeConfig } from 'vite'
142+
import { javascriptConfig } from '@nativescript/vite/javascript'
142143

143-
export default defineConfig(({ mode }): UserConfig => {
144-
return mergeConfig(typescriptConfig({ mode }), {})
144+
export default defineConfig(({ mode }) => {
145+
return mergeConfig(javascriptConfig({ mode }), {})
145146
})
146147
```
147148

@@ -167,9 +168,101 @@ You can also use an object form such as `typeCheck: { failOnError: false }`.
167168
For temporary overrides, `NS_VITE_TYPECHECK=warn` or `--env.typecheck=warn` will force warn mode for a run.
168169
If you want type errors to stay non-fatal without any Vite override, set `"noEmitOnError": false` in your project's `tsconfig.json`.
169170

171+
## Dev server and HMR
172+
173+
The NativeScript CLI owns the dev server lifecycle. For each session it picks:
174+
175+
- **Port** — the first free port at or above `NS_HMR_PORT` (default `5173`), the same way `vite` moves off a busy port. Whatever it picks is baked into the device URLs, bound by the dev server and (on Android) tunnelled with `adb reverse`, so all three always agree.
176+
- **Staging directory**`.ns-vite-build/<platform>`, so iOS and Android builds never overwrite each other's output.
177+
178+
The environment settings described below only need to be visible to the `ns` process — the CLI propagates them (and the values it picks) to the dev server it spawns.
179+
180+
### Running two platforms at once
181+
182+
Start both; nothing to configure:
183+
184+
```bash
185+
# Terminal 1
186+
ns debug ios # dev server on 5173
187+
188+
# Terminal 2
189+
ns debug android # 5173 is busy → dev server on 5174
190+
```
191+
192+
Each session gets its own port and staging directory.
193+
194+
### Android: automatic `adb reverse`
195+
196+
For Android HMR the CLI automatically runs `adb reverse tcp:<port> tcp:<port>` for the session's dev-server port, so the device reaches the dev server through the ADB tunnel at `127.0.0.1:<port>`. Relevant opt-outs:
197+
198+
- `NS_HMR_NO_ADB_REVERSE=1` — skip the tunnel and use `10.0.2.2`.
199+
- `NS_HMR_PREFER_LAN_HOST=1` — physical device over Wi-Fi; emit the host's LAN IP.
200+
- `NS_HMR_HOST=<host[:port]>` — point the device at an explicit origin (CI / tunnels).
201+
202+
### Advanced: running `vite serve` yourself
203+
204+
The dev server is a plain `vite serve -- --env.<platform> --env.hmr` invocation. You can run it standalone for diagnostics, but do **not** run it alongside `ns run`/`ns debug` for the same platform — both would try to bind the same port. CLI-managed is the supported default.
205+
206+
## Environment variables
207+
208+
All flags are read from the environment of the `ns` process (the CLI forwards them to the dev server it spawns).
209+
210+
### Dev server & connectivity
211+
212+
| Environment variable | Purpose | Default |
213+
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------- |
214+
| `NS_HMR_PORT` | Preferred Vite dev-server port; the CLI moves to the next free port when it is taken | `5173` |
215+
| `NS_HMR_STRICT_PORT` | Fail instead of moving when `NS_HMR_PORT` is taken (Vite's `strictPort`) — for tunnels / CI that forward a fixed port | unset |
216+
| `NS_HMR_HOST` | Explicit `host[:port]` origin baked into device URLs (CI / tunnels) | auto-detected |
217+
| `NS_HMR_PROTO` | Force `http` or `https` for device URLs, overriding the `NS_HTTPS` default | derived from `NS_HTTPS` |
218+
| `NS_HMR_PREFER_LAN_HOST` | `1` to emit the host's LAN IP — for a physical Android device over Wi-Fi | unset |
219+
| `NS_HMR_NO_ADB_REVERSE` | `1` to skip the automatic `adb reverse` tunnel and use `10.0.2.2` | unset |
220+
| `NS_HTTPS` | `1`/`true` to serve the dev server over TLS (also switches the HMR socket to `wss`) | unset |
221+
| `NS_HTTPS_KEY` / `NS_HTTPS_CERT` | Paths to the TLS key and certificate files used when `NS_HTTPS` is enabled | unset |
222+
| `NS_VITE_DIST_DIR` | Project-relative staging directory used for Vite output before the NativeScript CLI copies it into the platform app | `.ns-vite-build/<platform>` |
223+
224+
### Build & tooling
225+
226+
| Environment variable | Purpose | Default |
227+
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
228+
| `NS_VITE_VERBOSE` | `1`/`true` for verbose build logs (same as `--env.verbose`) | unset |
229+
| `NS_VITE_TYPECHECK` | Type-check mode override: `error`, `warn`, or `off` (see [Type checking](#type-checking)) | from `tsconfig.json` |
230+
| `NS_VITE_TYPECHECK_LOG` | `0`/`false` to suppress printing individual type diagnostics | enabled |
231+
| `NS_VITE_PROGRESS_OVERLAY` | `0`/`false` to disable the on-device HMR progress overlay | enabled |
232+
| `NS_NATIVE_ES_CLASSES` | `1` to skip the `@NativeClass` ES5 downlevel and let the iOS runtime register plain ES classes natively (same as `--env.nativeESClasses`; never applies to Android) | unset |
233+
| `NS_APP_COMPONENTS` | Comma-separated paths to custom Android `Activity`/`Application` classes to include in the bundle | unset |
234+
| `NS_VENDOR_INCLUDE` / `NS_VENDOR_EXCLUDE` | Comma-separated package names to force into / keep out of the dev-session vendor bundle | auto-detected |
235+
| `NS_DISABLE_OPTIMIZEDEPS` | `1` to disable Vite's dependency pre-bundling discovery | unset |
236+
237+
### Angular-specific
238+
239+
| Environment variable | Purpose | Default |
240+
| ----------------------------- | ------------------------------------------------------------------------------------ | ------- |
241+
| `NS_VITE_ANGULAR_LIVE_RELOAD` | `0`/`false`/`off`/`no` to disable the Analog `liveReload` component-update path | enabled |
242+
| `NS_STRICT_NG_LINK` | `1` to make Angular partial-compilation linking errors fatal instead of warnings | unset |
243+
| `NS_ENABLE_ROLLUP_LINKER` | `1` to run the Angular linker during the Rollup/Rolldown build (always on under HMR) | unset |
244+
245+
::: details Diagnostics and escape hatches (rarely needed)
246+
247+
These exist for profiling and unusual workflows; the defaults are correct for normal development.
248+
249+
- `NS_CORE_PER_MODULE=1` — serve `@nativescript/core` per-module instead of the single-eval core bundle (for live-editing core source in the NativeScript monorepo).
250+
- `NS_DEPS_PER_MODULE=1` — serve `node_modules` files per-module instead of the single-eval deps bundle (for `patch-package` workflows that edit `node_modules` mid-session).
251+
- `NS_VITE_HMR_DISABLE_POPULATE=1` — disable the server's background transform pre-population when profiling.
252+
- `NS_VITE_HMR_DISABLE_BOOT_RECORDING=1` — disable recording the boot URL set (used to speed up subsequent boots).
253+
- `NS_VITE_HMR_DISABLE_NSM_MEMO=1` — disable the served-module response memo cache.
254+
- `NS_VITE_HMR_TRANSFORM_CONCURRENCY=<n>` — override the transform fan-out (default `8`).
255+
- `NS_VITE_HMR_TRANSFORM_CACHE_MS=<ms>` — override the transform cache TTL.
256+
- `NS_VITE_HMR_BOOT_TRACE_IDLE_MS=<ms>` / `NS_VITE_HMR_BOOT_RECORD_IDLE_MS=<ms>` / `NS_VITE_HMR_BOOT_TRACE_PROGRESS_EVERY=<n>` — tune boot tracing/recording windows when profiling boot.
257+
- `NS_DEBUG_NATIVECLASS=1` — verbose logs from the `@NativeClass` transform.
258+
- `NS_CORE_EXTERNAL_DEBUG=1` — verbose logs from the `@nativescript/core` URL externalizer.
259+
- `NS_HMR_SELF_COMPILE_TEMPLATE=1` — (Vue) prefer self-compiled SFC template variants when serving.
260+
261+
:::
262+
170263
## Advanced: HMR update hooks
171264

172-
When using the HMR workflow (for example `npm run dev:ios` / `npm run dev:android` / `npm run dev:visionos`, etc.), you may want to run some custom logic after each HMR batch is applied on device.
265+
When running with HMR (the default `ns debug` workflow), you may want to run some custom logic after each HMR batch is applied on device.
173266

174267
`@nativescript/vite` exposes a low-level hook for this:
175268

@@ -252,16 +345,22 @@ Disable HMR (enabled by default)
252345

253346
Prints verbose logs and the internal config before building
254347

348+
### --env.typecheck
349+
350+
Override the type-check mode for a run, e.g. `--env.typecheck=warn` (see [Type checking](#type-checking))
351+
352+
### --env.nativeESClasses
353+
354+
Skip the `@NativeClass` ES5 downlevel on Apple targets (same as `NS_NATIVE_ES_CLASSES=1`)
355+
255356
### Additional flags
256357

257-
Additional env flags that are usually passed by the CLI automatically
358+
Additional env flags that are passed by the CLI automatically
258359

259-
- `--env.appPath` - path to the app source (same as `appPath` in the `nativescript.config.ts`)
260-
- `--env.appResourcesPath` - path to App_Resources (same as `appResourcesPath` in the `nativescript.config.ts`)
261-
- `--env.nativescriptLibPath` - path to the currently running CLI's library.
262-
- `--env.android` - `true` when running on android
263-
- `--env.ios` - `true` when running on ios
264-
- `--env.platform=<platform>` - for specifying the platform to use. Can be `android` or `ios`, or a custom platform in the future.
360+
- `--env.android` - `true` when running on Android
361+
- `--env.ios` - `true` when running on iOS
362+
- `--env.visionos` - `true` when running on visionOS
363+
- `--env.platform=<platform>` - for specifying the platform to use. Can be `android`, `ios`, or `visionos`.
265364
- `--env.hmr` - `true` when building with HMR enabled
266365

267366
## Global "magic" variables
@@ -292,25 +391,34 @@ We define a few useful globally available variables that you can use to alter lo
292391
// we are running on visionOS
293392
}
294393
```
394+
- `__APPLE__`, `true` when the platform is iOS or visionOS
395+
```ts
396+
if (__APPLE__) {
397+
// we are running on an Apple platform
398+
}
399+
```
295400

296401
::: details The following variables are also defined, but are primarily intended to be used by NativeScript Core internally, or plugins that wish to use these.
297402

298403
- `__NS_ENV_VERBOSE__` - `true` when `--env.verbose` is set
299-
- `__CSS_PARSER__` - the CSS parser used by NativeScript Core. The value is set based on the `cssParser` value in the `nativescript.config.ts` and defaults to `css-tree`
404+
- `__NS_WEBPACK__` - always `false` under Vite; lets plugins detect which bundler built the app
405+
- `__CSS_PARSER__` - the CSS parser used by NativeScript Core (`css-tree` under Vite)
300406
- `__UI_USE_XML_PARSER__` - a flag used by NativeScript Core to disable the XML parser when it's not used
301407
- `__UI_USE_EXTERNAL_RENDERER__` - a flag used by NativeScript Core to disable registering global modules when an external renderer is used.
408+
- `__CI__` - `true` when the build runs in a CI environment
409+
- `__TEST__` - `false` in app builds; various ecosystems (React, for example) check this global
302410

303411
:::
304412

305413
## Configuration examples
306414

307-
Here are some common examples of things you may want to do in your `vite.config.ts`.
415+
Here are some common examples of things you may want to do in your `vite.config.mts`.
308416

309417
### Adding a copy rule
310418

311419
```ts
312420
import { defineConfig, mergeConfig, UserConfig } from 'vite'
313-
import { typescriptConfig } from '@nativescript/vite'
421+
import { typescriptConfig } from '@nativescript/vite/typescript'
314422
import path from 'path'
315423
import { viteStaticCopy } from 'vite-plugin-static-copy'
316424

@@ -403,7 +511,7 @@ If you see your app is not building with Vite, ensure that your `nativescript.co
403511
export default {
404512
// ...
405513
bundler: 'vite',
406-
bundlerConfigPath: 'vite.config.ts',
514+
bundlerConfigPath: 'vite.config.mts',
407515
// ...
408516
}
409517
```

content/project-structure/vite-config.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
---
2-
title: vite.config.ts
2+
title: vite.config.mts
33
description: NativeScript apps can be bundled with Vite, giving you flexibility to configure any way you need.
44
contributors:
55
- NathanWalker
66
---
77

8-
At anytime you can switch to Vite build tooling if you prefer. The bundling process can be further customized via the `vite.config.ts`.
8+
At anytime you can switch to Vite build tooling if you prefer. The bundling process can be further customized via the `vite.config.mts`.
99

1010
### Default vite config
1111

1212
By default, the vite config will automatically configure everything for your project, and should looks something like this:
1313

14-
```js
14+
```ts
1515
import { defineConfig, mergeConfig, UserConfig } from 'vite'
16-
import { typescriptConfig } from '@nativescript/vite'
16+
import { typescriptConfig } from '@nativescript/vite/typescript'
1717

1818
export default defineConfig(({ mode }): UserConfig => {
1919
return mergeConfig(typescriptConfig({ mode }), {})

content/sidebar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ export default [
124124
icon: 'file',
125125
},
126126
{
127-
text: 'vite.config.ts',
127+
text: 'vite.config.mts',
128128
link: '/project-structure/vite-config',
129129
icon: 'file',
130130
},

0 commit comments

Comments
 (0)