@nuxt/docs-nightly 4.6.0-29803612.ea5d49fb → 4.6.0-29809999.0506e6c6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/1.getting-started/17.testing.md +162 -15
- package/1.getting-started/18.upgrade.md +74 -0
- package/2.directory-structure/1.app/3.app-config.md +2 -2
- package/3.guide/6.going-further/1.experimental-features.md +95 -0
- package/3.guide/6.going-further/8.builders.md +24 -0
- package/4.api/6.advanced/1.hooks.md +1 -0
- package/package.json +1 -1
|
@@ -265,16 +265,15 @@ Under the hood, `mountSuspended` wraps `mount` from `@vue/test-utils`, so you ca
|
|
|
265
265
|
|
|
266
266
|
For example:
|
|
267
267
|
|
|
268
|
-
```ts twoslash
|
|
268
|
+
```ts twoslash [tests/components/SomeComponents.nuxt.spec.ts]
|
|
269
269
|
// @noErrors
|
|
270
|
-
import { expect, it } from 'vitest'
|
|
271
270
|
import type { Component } from 'vue'
|
|
272
271
|
|
|
273
272
|
declare module '#components' {
|
|
274
273
|
export const SomeComponent: Component
|
|
275
274
|
}
|
|
276
275
|
// ---cut---
|
|
277
|
-
|
|
276
|
+
import { expect, it } from 'vitest'
|
|
278
277
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
279
278
|
import { SomeComponent } from '#components'
|
|
280
279
|
|
|
@@ -286,15 +285,11 @@ it('can mount some component', async () => {
|
|
|
286
285
|
})
|
|
287
286
|
```
|
|
288
287
|
|
|
289
|
-
```ts twoslash
|
|
290
|
-
// @noErrors
|
|
288
|
+
```ts twoslash [tests/App.nuxt.spec.ts]
|
|
291
289
|
import { expect, it } from 'vitest'
|
|
292
|
-
// ---cut---
|
|
293
|
-
// tests/components/SomeComponents.nuxt.spec.ts
|
|
294
290
|
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
295
291
|
import App from '~/app.vue'
|
|
296
292
|
|
|
297
|
-
// tests/App.nuxt.spec.ts
|
|
298
293
|
it('can also mount an app', async () => {
|
|
299
294
|
const component = await mountSuspended(App, { route: '/test' })
|
|
300
295
|
expect(component.html()).toMatchInlineSnapshot(`
|
|
@@ -306,9 +301,34 @@ it('can also mount an app', async () => {
|
|
|
306
301
|
})
|
|
307
302
|
```
|
|
308
303
|
|
|
304
|
+
If you need to spy on component setup state, you can set the `spy` option to `true` and access the return value of the setup via `setupState`.
|
|
305
|
+
|
|
306
|
+
```ts twoslash [tests/components/SomeComponents.nuxt.spec.ts]
|
|
307
|
+
// @noErrors
|
|
308
|
+
import type { Component } from 'vue'
|
|
309
|
+
|
|
310
|
+
declare module '#components' {
|
|
311
|
+
export const SomeComponent: Component
|
|
312
|
+
}
|
|
313
|
+
// ---cut---
|
|
314
|
+
import { expect, it, vi } from 'vitest'
|
|
315
|
+
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
316
|
+
import { SomeComponent } from '#components'
|
|
317
|
+
|
|
318
|
+
it('can spy on setup state', async () => {
|
|
319
|
+
const component = await mountSuspended(SomeComponent, { spy: true })
|
|
320
|
+
vi.mocked(component.setupState.someMethod).mockImplementation(() => 'mocked')
|
|
321
|
+
})
|
|
322
|
+
```
|
|
323
|
+
|
|
309
324
|
The options object accepts `@vue/test-utils` mount options and the following properties:
|
|
310
325
|
|
|
311
326
|
- `route`: the initial route, or `false` to skip the initial route change (default `/`).
|
|
327
|
+
- `spy`: enable spy component setup state (default `false`).
|
|
328
|
+
|
|
329
|
+
The return object includes the `@vue/test-utils` mount result and the following properties:
|
|
330
|
+
|
|
331
|
+
- `setupState`: the return value of the component setup.
|
|
312
332
|
|
|
313
333
|
#### `renderSuspended`
|
|
314
334
|
|
|
@@ -322,16 +342,15 @@ The passed in component will be rendered inside a `<div id="test-wrapper"></div>
|
|
|
322
342
|
|
|
323
343
|
Examples:
|
|
324
344
|
|
|
325
|
-
```ts twoslash
|
|
345
|
+
```ts twoslash [tests/components/SomeComponents.nuxt.spec.ts]
|
|
326
346
|
// @noErrors
|
|
327
|
-
import { expect, it } from 'vitest'
|
|
328
347
|
import type { Component } from 'vue'
|
|
329
348
|
|
|
330
349
|
declare module '#components' {
|
|
331
350
|
export const SomeComponent: Component
|
|
332
351
|
}
|
|
333
352
|
// ---cut---
|
|
334
|
-
|
|
353
|
+
import { expect, it } from 'vitest'
|
|
335
354
|
import { renderSuspended } from '@nuxt/test-utils/runtime'
|
|
336
355
|
import { SomeComponent } from '#components'
|
|
337
356
|
import { screen } from '@testing-library/vue'
|
|
@@ -342,11 +361,8 @@ it('can render some component', async () => {
|
|
|
342
361
|
})
|
|
343
362
|
```
|
|
344
363
|
|
|
345
|
-
```ts twoslash
|
|
346
|
-
// @noErrors
|
|
364
|
+
```ts twoslash [tests/App.nuxt.spec.ts]
|
|
347
365
|
import { expect, it } from 'vitest'
|
|
348
|
-
// ---cut---
|
|
349
|
-
// tests/App.nuxt.spec.ts
|
|
350
366
|
import { renderSuspended } from '@nuxt/test-utils/runtime'
|
|
351
367
|
import App from '~/app.vue'
|
|
352
368
|
|
|
@@ -365,6 +381,11 @@ it('can also render an app', async () => {
|
|
|
365
381
|
The options object accepts `@testing-library/vue` render options and the following properties:
|
|
366
382
|
|
|
367
383
|
- `route`: the initial route, or `false` to skip the initial route change (default `/`).
|
|
384
|
+
- `spy`: enable spy component setup state (default `false`). See the [`mountSuspended`](#mountsuspended) example above.
|
|
385
|
+
|
|
386
|
+
The return object includes the `@testing-library/vue` render result and the following properties:
|
|
387
|
+
|
|
388
|
+
- `setupState`: the return value of the component setup.
|
|
368
389
|
|
|
369
390
|
#### `mockNuxtImport`
|
|
370
391
|
|
|
@@ -658,6 +679,132 @@ If you prefer to use `@vue/test-utils` on its own for unit testing in Nuxt, and
|
|
|
658
679
|
|
|
659
680
|
Congratulations, you're all set to start unit testing with `@vue/test-utils` in Nuxt! Happy testing!
|
|
660
681
|
|
|
682
|
+
### Vitest Browser Mode
|
|
683
|
+
|
|
684
|
+
`@nuxt/test-utils` provides helpers for testing in [Vitest Browser Mode](https://vitest.dev/guide/browser/) via `@nuxt/test-utils/browser`.
|
|
685
|
+
|
|
686
|
+
#### Setup
|
|
687
|
+
|
|
688
|
+
1. Install Vitest browser packages and a browser provider:
|
|
689
|
+
|
|
690
|
+
::code-group{sync="pm"}
|
|
691
|
+
```bash [npm]
|
|
692
|
+
npm i --save-dev @vitest/browser-playwright
|
|
693
|
+
```
|
|
694
|
+
```bash [yarn]
|
|
695
|
+
yarn add --dev @vitest/browser-playwright
|
|
696
|
+
```
|
|
697
|
+
```bash [pnpm]
|
|
698
|
+
pnpm add -D @vitest/browser-playwright
|
|
699
|
+
```
|
|
700
|
+
```bash [bun]
|
|
701
|
+
bun add --dev @vitest/browser-playwright
|
|
702
|
+
```
|
|
703
|
+
::
|
|
704
|
+
|
|
705
|
+
2. Configure browser mode in your `vitest.config.ts`:
|
|
706
|
+
|
|
707
|
+
```ts twoslash
|
|
708
|
+
// @errors: 2307
|
|
709
|
+
// ---cut---
|
|
710
|
+
import { defineConfig } from 'vitest/config'
|
|
711
|
+
import { defineVitestProject } from '@nuxt/test-utils/config'
|
|
712
|
+
import { playwright } from '@vitest/browser-playwright'
|
|
713
|
+
|
|
714
|
+
export default defineConfig({
|
|
715
|
+
test: {
|
|
716
|
+
projects: [
|
|
717
|
+
await defineVitestProject({
|
|
718
|
+
test: {
|
|
719
|
+
name: 'browser',
|
|
720
|
+
include: ['test/browser/**/*.{test,spec}.ts'],
|
|
721
|
+
browser: {
|
|
722
|
+
enabled: true,
|
|
723
|
+
provider: playwright(),
|
|
724
|
+
instances: [{ browser: 'chromium' }],
|
|
725
|
+
},
|
|
726
|
+
// If you want to enable `page.render` and automatic cleanup, add this setup file
|
|
727
|
+
setupFiles: ['@nuxt/test-utils/browser'],
|
|
728
|
+
},
|
|
729
|
+
}),
|
|
730
|
+
],
|
|
731
|
+
},
|
|
732
|
+
})
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
::note
|
|
736
|
+
When adding `@nuxt/test-utils/browser` to `setupFiles`, if TypeScript does not automatically recognize the types for `page.render`, you can add `@nuxt/test-utils/browser` via `typescript.tsConfig.compilerOptions.types` in your `nuxt.config.ts`.
|
|
737
|
+
::
|
|
738
|
+
|
|
739
|
+
::note
|
|
740
|
+
If your Vitest browser mode tests live outside `test/nuxt/` (such as in `test/browser/`), see [Adding other test directories](#adding-other-test-directories) to add them to the TypeScript context.
|
|
741
|
+
::
|
|
742
|
+
|
|
743
|
+
#### Usage
|
|
744
|
+
|
|
745
|
+
You can use `page.render` from `vitest/browser`:
|
|
746
|
+
|
|
747
|
+
```ts twoslash [test/browser/components/MyCounter.nuxt.spec.ts]
|
|
748
|
+
// @noErrors
|
|
749
|
+
import type { Component } from 'vue'
|
|
750
|
+
|
|
751
|
+
declare module '#components' {
|
|
752
|
+
export const MyCounter: Component
|
|
753
|
+
}
|
|
754
|
+
// ---cut---
|
|
755
|
+
import { expect, it } from 'vitest'
|
|
756
|
+
import { page } from 'vitest/browser'
|
|
757
|
+
// If you added the setup file, the following import is not needed
|
|
758
|
+
import '@nuxt/test-utils/browser'
|
|
759
|
+
|
|
760
|
+
import { MyCounter } from '#components'
|
|
761
|
+
|
|
762
|
+
it('counter button increments the count', async () => {
|
|
763
|
+
const screen = await page.render(MyCounter)
|
|
764
|
+
await screen.getByRole('button', { name: 'Increment' }).click()
|
|
765
|
+
await expect.element(screen.getByText('Count: 1')).toBeVisible()
|
|
766
|
+
})
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
You can also import `render` directly from `@nuxt/test-utils/browser`:
|
|
770
|
+
|
|
771
|
+
```ts twoslash
|
|
772
|
+
// @noErrors
|
|
773
|
+
import type { Component } from 'vue'
|
|
774
|
+
|
|
775
|
+
declare module '#components' {
|
|
776
|
+
export const MyCounter: Component
|
|
777
|
+
}
|
|
778
|
+
// ---cut---
|
|
779
|
+
import { expect, it } from 'vitest'
|
|
780
|
+
import { render } from '@nuxt/test-utils/browser'
|
|
781
|
+
import { MyCounter } from '#components'
|
|
782
|
+
|
|
783
|
+
it('can render using the render helper', async () => {
|
|
784
|
+
const screen = await render(MyCounter)
|
|
785
|
+
await screen.getByRole('button', { name: 'Increment' }).click()
|
|
786
|
+
await expect.element(screen.getByText('Count: 1')).toBeVisible()
|
|
787
|
+
})
|
|
788
|
+
```
|
|
789
|
+
|
|
790
|
+
The options object accepts `@vue/test-utils` mount options (use `container` instead of `attachTo`) and the following properties:
|
|
791
|
+
|
|
792
|
+
- `route`: the initial route, or `false` to skip the initial route change (default `/`).
|
|
793
|
+
- `spy`: enable spy component setup state (default `false`). See the [`mountSuspended`](#mountsuspended) example above.
|
|
794
|
+
- `container`: custom `HTMLElement` container to render into (use this option instead of `@vue/test-utils` `attachTo`).
|
|
795
|
+
- `baseElement`: custom base `HTMLElement` (default `document.body`).
|
|
796
|
+
|
|
797
|
+
The return object includes the following properties:
|
|
798
|
+
|
|
799
|
+
- `container`: the container `HTMLElement` the component is rendered into.
|
|
800
|
+
- `baseElement`: the base `HTMLElement` (default `document.body`).
|
|
801
|
+
- `locator`: root element `Locator`.
|
|
802
|
+
- `setupState`: the return value of the component setup, mocked when the `spy` option is enabled.
|
|
803
|
+
- `debug()`: print formatted DOM to console.
|
|
804
|
+
- `unmount()`: unmount the component. Also records a `nuxt.unmount` trace mark.
|
|
805
|
+
- `emitted()`: get emitted events.
|
|
806
|
+
- `rerender(props)`: re-render the component with new props. Also records a `nuxt.rerender` trace mark.
|
|
807
|
+
|
|
661
808
|
## End-To-End Testing
|
|
662
809
|
|
|
663
810
|
For end-to-end testing, we support [Vitest](https://github.com/vitest-dev/vitest), [Jest](https://jestjs.io), [Cucumber](https://cucumber.io/) and [Playwright](https://playwright.dev/) as test runners.
|
|
@@ -551,6 +551,80 @@ export default defineNuxtConfig({
|
|
|
551
551
|
})
|
|
552
552
|
```
|
|
553
553
|
|
|
554
|
+
### Typed `$fetch` Rebuilt on Generated Route Types
|
|
555
|
+
|
|
556
|
+
🚦 **Impact Level**: Medium
|
|
557
|
+
|
|
558
|
+
#### What Changed
|
|
559
|
+
|
|
560
|
+
With `compatibilityVersion: 5`, `$fetch` and `useFetch` are typed from the routes Nuxt's server
|
|
561
|
+
builder reports, rather than from nitro's `InternalApi` interface. As well as response types, a
|
|
562
|
+
`body`, `query` or `headers` the matching handler validates are now enforced on the call, a method
|
|
563
|
+
the route does not handle is rejected, and a response is typed as it arrives over the wire, so a
|
|
564
|
+
`Date` a handler returns is a `string` at the call site.
|
|
565
|
+
|
|
566
|
+
Two things follow from this:
|
|
567
|
+
|
|
568
|
+
- Routes you augmented by hand on nitro's `InternalApi` are no longer picked up. Augment
|
|
569
|
+
`ServerRoutes` from `@nuxt/schema` instead.
|
|
570
|
+
- The `params` option is no longer accepted by `$fetch` or `useFetch`. It was an alias for `query`.
|
|
571
|
+
|
|
572
|
+
#### Reasons for Change
|
|
573
|
+
|
|
574
|
+
Nitro v3 drops typed fetch, and the old implementation did not scale past about 300 routes. The new
|
|
575
|
+
generated route types cost the same to check whatever the route count, and carry enough information
|
|
576
|
+
to type the request as well as the response. `params` is dropped so the name is free for named route
|
|
577
|
+
parameters later.
|
|
578
|
+
|
|
579
|
+
#### Migration Steps
|
|
580
|
+
|
|
581
|
+
Move any `params` option to `query`:
|
|
582
|
+
|
|
583
|
+
```diff
|
|
584
|
+
const { data } = await useFetch('/api/search', {
|
|
585
|
+
- params: { q: 'nuxt' },
|
|
586
|
+
+ query: { q: 'nuxt' },
|
|
587
|
+
})
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
Move any manual route augmentation from `InternalApi` to `ServerRoutes`:
|
|
591
|
+
|
|
592
|
+
```diff [shared/server-routes.d.ts]
|
|
593
|
+
- declare module 'nitropack' {
|
|
594
|
+
- interface InternalApi {
|
|
595
|
+
- '/api/hello': { get: { message: string } }
|
|
596
|
+
- }
|
|
597
|
+
- }
|
|
598
|
+
+ import type { Endpoint } from 'nuxt/app'
|
|
599
|
+
+
|
|
600
|
+
+ declare module '@nuxt/schema' {
|
|
601
|
+
+ interface ServerRoutes {
|
|
602
|
+
+ '/api/hello': {
|
|
603
|
+
+ [Endpoint]: {
|
|
604
|
+
+ GET: { response: { message: string } }
|
|
605
|
+
+ }
|
|
606
|
+
+ }
|
|
607
|
+
+ }
|
|
608
|
+
+ }
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
::note
|
|
612
|
+
While Nuxt 4 runs on nitro v2, nitro declares a global `$fetch` of its own, typed from
|
|
613
|
+
`InternalApi`. Import `$fetch` from `#build/fetch` where you want the generated route types to apply
|
|
614
|
+
to a direct call; `useFetch`, `useLazyFetch` and `useRequestFetch()` are unaffected.
|
|
615
|
+
::
|
|
616
|
+
|
|
617
|
+
::tip
|
|
618
|
+
Either typing can be selected on its own with
|
|
619
|
+
[`experimental.routeTypedFetch`](/docs/4.x/guide/going-further/experimental-features#routetypedfetch),
|
|
620
|
+
so you can adopt this before moving to Nuxt 5, or move to Nuxt 5 with `routeTypedFetch: false` and
|
|
621
|
+
adopt it separately. The option is temporary: from Nuxt 5 the generated route set is the only
|
|
622
|
+
source.
|
|
623
|
+
::
|
|
624
|
+
|
|
625
|
+
Set [`experimental.strictRouteTypes`](/docs/4.x/guide/going-further/experimental-features#strictroutetypes)
|
|
626
|
+
to reject a path no route answers.
|
|
627
|
+
|
|
554
628
|
### TypeScript `baseUrl` Is Ignored
|
|
555
629
|
|
|
556
630
|
🚦 **Impact Level**: Minimal
|
|
@@ -67,7 +67,7 @@ Read more about the `updateAppConfig` utility.
|
|
|
67
67
|
|
|
68
68
|
Nuxt tries to automatically generate a TypeScript interface from provided app config so you won't have to type it yourself.
|
|
69
69
|
|
|
70
|
-
The fully inferred type is only available in app code (components, composables, plugins and so on). In server routes, code in the `shared/` directory and `nuxt.config`, keys defined in `app.config` files are typed as `unknown` instead: typing them there would require typechecking your app code outside the app context, where app auto-imports are not available. Keys defined inline in the `appConfig` option of `nuxt.config` are typed everywhere. If you need other keys typed outside app code, you can extend the `
|
|
70
|
+
The fully inferred type is only available in app code (components, composables, plugins and so on). In server routes, code in the `shared/` directory and `nuxt.config`, keys defined in `app.config` files are typed as `unknown` instead: typing them there would require typechecking your app code outside the app context, where app auto-imports are not available. Keys defined inline in the `appConfig` option of `nuxt.config` are typed everywhere. If you need other keys typed outside app code, you can extend the `SharedAppConfig` interface as described below. The location of the augmentation file determines which contexts see it: a `.d.ts` file in the `shared/` directory covers app code, shared code and server routes.
|
|
71
71
|
|
|
72
72
|
However, there are some cases where you might want to type it yourself. There are two possible things you might want to type.
|
|
73
73
|
|
|
@@ -92,7 +92,7 @@ export {}
|
|
|
92
92
|
|
|
93
93
|
### App Config Output
|
|
94
94
|
|
|
95
|
-
If you want to type the result of calling [`useAppConfig()`](/docs/4.x/api/composables/use-app-config), then you will want to extend `AppConfig`.
|
|
95
|
+
If you want to type the result of calling [`useAppConfig()`](/docs/4.x/api/composables/use-app-config) in app code, then you will want to extend `AppConfig`. Outside app code (server routes, the `shared/` directory and `nuxt.config`) `useAppConfig()` returns `SharedAppConfig`, so extend that interface instead.
|
|
96
96
|
|
|
97
97
|
::warning
|
|
98
98
|
Be careful when typing `AppConfig` as you will overwrite the types Nuxt infers from your actually defined app config.
|
|
@@ -1050,6 +1050,101 @@ export default defineNuxtConfig({
|
|
|
1050
1050
|
})
|
|
1051
1051
|
```
|
|
1052
1052
|
|
|
1053
|
+
## routeTypedFetch
|
|
1054
|
+
|
|
1055
|
+
Type `$fetch` and `useFetch` from the routes your server builder reports, rather than from the
|
|
1056
|
+
responses nitro contributes to `ServerRoutes` through its `InternalApi` interface.
|
|
1057
|
+
|
|
1058
|
+
```ts twoslash [nuxt.config.ts]
|
|
1059
|
+
export default defineNuxtConfig({
|
|
1060
|
+
experimental: {
|
|
1061
|
+
routeTypedFetch: true,
|
|
1062
|
+
},
|
|
1063
|
+
})
|
|
1064
|
+
```
|
|
1065
|
+
|
|
1066
|
+
The generated route set carries the `body`, `query` and `headers` a handler validates as well as its
|
|
1067
|
+
response, typed as it arrives over the wire, so a resolving call is typed more tightly than before:
|
|
1068
|
+
|
|
1069
|
+
- a `Date` a handler returns is a `string` at the call site
|
|
1070
|
+
- a `body` the handler validates cannot be omitted or given the wrong shape
|
|
1071
|
+
- a method the route does not answer is rejected
|
|
1072
|
+
- `params` is no longer accepted, since it was only ever an alias for `query`
|
|
1073
|
+
- a route you registered by augmenting `ServerRoutes` by hand needs rewriting, as the two
|
|
1074
|
+
descriptions of a route differ (see [the upgrade guide](/docs/4.x/getting-started/upgrade#typed-fetch-rebuilt-on-generated-route-types))
|
|
1075
|
+
|
|
1076
|
+
Because of those, it is opt-in, and `future.compatibilityVersion: 5` enables it. Setting it
|
|
1077
|
+
explicitly selects either typing whatever the compatibility version, so you can adopt it before
|
|
1078
|
+
moving to Nuxt 5, or move to Nuxt 5 with `routeTypedFetch: false` and adopt it separately.
|
|
1079
|
+
|
|
1080
|
+
::note
|
|
1081
|
+
This option exists only while both typings are supported. From Nuxt 5 the generated route set is the
|
|
1082
|
+
only source and the option is gone.
|
|
1083
|
+
::
|
|
1084
|
+
|
|
1085
|
+
::note
|
|
1086
|
+
While Nuxt 4 runs on nitro v2, nitro declares a global `$fetch` of its own, typed from
|
|
1087
|
+
`InternalApi`. Import `$fetch` from `#build/fetch` where you want the generated route types to apply
|
|
1088
|
+
to a direct call; `useFetch`, `useLazyFetch` and `useRequestFetch()` are unaffected.
|
|
1089
|
+
::
|
|
1090
|
+
|
|
1091
|
+
## strictRouteTypes
|
|
1092
|
+
|
|
1093
|
+
Reject a request to a path no server route answers. Requires
|
|
1094
|
+
[`routeTypedFetch`](#routetypedfetch), which types `$fetch` and `useFetch` from the routes your
|
|
1095
|
+
server will serve.
|
|
1096
|
+
|
|
1097
|
+
```ts twoslash [nuxt.config.ts]
|
|
1098
|
+
export default defineNuxtConfig({
|
|
1099
|
+
experimental: {
|
|
1100
|
+
routeTypedFetch: true,
|
|
1101
|
+
strictRouteTypes: true,
|
|
1102
|
+
},
|
|
1103
|
+
})
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
With `routeTypedFetch` enabled a response is typed by the handler that answers it whatever this
|
|
1107
|
+
option is set to. What the option decides is whether a path Nuxt does not recognise is an error or
|
|
1108
|
+
is simply typed as `unknown`.
|
|
1109
|
+
|
|
1110
|
+
- `false` (default) - a path Nuxt does not recognise is accepted and resolves to `unknown`, and no
|
|
1111
|
+
method is rejected. Nuxt cannot see every way a request may be answered: nitro middleware, a
|
|
1112
|
+
[`routeRules`](/docs/4.x/guide/concepts/rendering#hybrid-rendering) proxy or a catch-all handler
|
|
1113
|
+
can answer a path no route describes.
|
|
1114
|
+
- `true` - only the routes your server builder reports are accepted, for the methods they answer.
|
|
1115
|
+
- `'isomorphic'` - as `true`, and your pages are included as `GET` routes returning `string`, so
|
|
1116
|
+
`$fetch('/about')` is typed by the route the Vue router serves rather than rejected.
|
|
1117
|
+
|
|
1118
|
+
With the option on, a typo and a method the route does not answer are both errors:
|
|
1119
|
+
|
|
1120
|
+
```ts
|
|
1121
|
+
// server/api/todos.post.ts answers POST only
|
|
1122
|
+
await $fetch('/api/todos', { method: 'POST' })
|
|
1123
|
+
await $fetch('/api/todo', { method: 'POST' })
|
|
1124
|
+
// ^ no POST route matches '/api/todo'
|
|
1125
|
+
await $fetch('/api/todos')
|
|
1126
|
+
// ^ no GET route matches '/api/todos'
|
|
1127
|
+
```
|
|
1128
|
+
|
|
1129
|
+
Two things stay accepted, because they are not Nuxt's to describe: an absolute URL
|
|
1130
|
+
(`$fetch('https://example.com')`), and a path built at runtime, which resolves to `unknown` as it
|
|
1131
|
+
does with the option off. A `baseURL` is resolved into the path before it is matched, so a request
|
|
1132
|
+
made through one is checked against the route it actually asks for. Naming the response type also
|
|
1133
|
+
opts a call out, since doing so turns off inference for the request:
|
|
1134
|
+
|
|
1135
|
+
```ts
|
|
1136
|
+
const data = await $fetch<{ id: string }>(`/api/${resource}`)
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
::note
|
|
1140
|
+
Files in your `public/` directory are not routes your server builder reports, so requesting one
|
|
1141
|
+
with `strictRouteTypes` enabled is an error. Fetch those with an explicit response type, or leave
|
|
1142
|
+
the option off.
|
|
1143
|
+
::
|
|
1144
|
+
|
|
1145
|
+
Set this only where your routing is enumerable. An app with a catch-all page under `'isomorphic'`
|
|
1146
|
+
matches every path, which is correct but means the option constrains nothing.
|
|
1147
|
+
|
|
1053
1148
|
## pendingWhenIdle
|
|
1054
1149
|
|
|
1055
1150
|
`pendingWhenIdle` controls the `pending` ref returned by `useAsyncData` and `useFetch`.
|
|
@@ -211,6 +211,30 @@ In development, a builder is also responsible for serving and hot-reloading the
|
|
|
211
211
|
|
|
212
212
|
In dev, the build outputs are typically wired to live, in-memory sources rather than on-disk files. For instance, the SSR entry may be served from the bundler's in-memory output, and the client manifest may be computed from the dev module graph, rather than read from `nuxt.options.buildDir`.
|
|
213
213
|
|
|
214
|
+
## Describing the Build to a Deploy Target
|
|
215
|
+
|
|
216
|
+
A server builder describes what it produced, so that tooling that deploys or previews the build does not have to know which builder ran. The description lives on `nuxt.serverBuild`, and is read with `useServerBuild()` from `@nuxt/kit/internal`:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
import { useServerBuild } from '@nuxt/kit/internal'
|
|
220
|
+
|
|
221
|
+
const build = useServerBuild()
|
|
222
|
+
|
|
223
|
+
build.output.root() // the project root: where a target's own config file lives
|
|
224
|
+
build.output.dir() // the build output directory
|
|
225
|
+
build.output.publicDir() // the deployable static assets within it
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
Every path is a function, because a builder may only resolve it while initialising, so call them from a hook that runs after the server builder has run.
|
|
229
|
+
|
|
230
|
+
The description also says how the server build relates to the app build. A server builder sets `buildsSeparately` to declare whether its build is a pass of its own, run after the app build (as `@nuxt/nitro-server` does), or whether the app builder is building everything and there is no separate pass (as with `@nuxt/vite-server`). Anything that needs to know reads it from the description rather than sniffing for a Nitro instance.
|
|
231
|
+
|
|
232
|
+
`output.root()` is deliberately not a bundler root. Nuxt points Vite's `root` at [`srcDir`](/docs/4.x/api/nuxt-config#srcdir), so a deploy target that resolves its configuration file (or the paths written inside it) from the bundler's root looks inside your app directory rather than at the root of your project. A target that reads the description resolves both correctly.
|
|
233
|
+
|
|
234
|
+
::warning
|
|
235
|
+
`nuxt.serverBuild` and the `setServerBuild()` / `useServerBuild()` helpers are experimental and exported from `@nuxt/kit/internal`. The shape will change without a major release while a second server builder is being built out.
|
|
236
|
+
::
|
|
237
|
+
|
|
214
238
|
::read-more{to="/docs/4.x/guide/going-further/internals"}
|
|
215
239
|
Learn more about the Nuxt interface and the build vs. runtime split.
|
|
216
240
|
::
|
|
@@ -57,6 +57,7 @@ Check the [schema source code](https://github.com/nuxt/nuxt/blob/main/packages/s
|
|
|
57
57
|
| `pages:extend` | `pages` | Called after page routes are scanned from the file system. |
|
|
58
58
|
| `pages:resolved` | `pages` | Called after page routes have been augmented with scanned metadata. |
|
|
59
59
|
| `pages:routerOptions` | `{ files: Array<{ path: string, optional?: boolean }> }` | Called when resolving `router.options` files. Later items in the array override earlier ones. |
|
|
60
|
+
| `server:routes` | `routes`, `context` | Called when Nuxt needs the full set of route handlers the server will serve, so that it can type `$fetch` and `useFetch` against them. |
|
|
60
61
|
| `server:devHandler` | `handler` | Called when the dev middleware is being registered on the Nitro dev server. |
|
|
61
62
|
| `imports:sources` | `presets` | Called at setup allowing modules to extend sources. |
|
|
62
63
|
| `imports:extend` | `imports` | Called at setup allowing modules to extend imports. |
|